Compare commits
1 Commits
cca53b2d26
...
v2.0.2-rc
Author | SHA1 | Date | |
---|---|---|---|
8dd46b8ad8 |
@ -23,6 +23,7 @@ cppflags
|
|||||||
cpphttplib
|
cpphttplib
|
||||||
cpptrace
|
cpptrace
|
||||||
cppvsdbg
|
cppvsdbg
|
||||||
|
create_notraverse
|
||||||
crypto_aead_xchacha20poly1305_ietf_npubbytes
|
crypto_aead_xchacha20poly1305_ietf_npubbytes
|
||||||
cstdint
|
cstdint
|
||||||
cxxflags
|
cxxflags
|
||||||
@ -30,6 +31,7 @@ cxxstd
|
|||||||
d_largefile64_source
|
d_largefile64_source
|
||||||
d_largefile_source
|
d_largefile_source
|
||||||
d_ndebug
|
d_ndebug
|
||||||
|
dacl_security_information
|
||||||
dbackward_shared
|
dbackward_shared
|
||||||
dbghelp
|
dbghelp
|
||||||
dboost_root
|
dboost_root
|
||||||
@ -94,6 +96,7 @@ expect_streq
|
|||||||
fallocate_impl
|
fallocate_impl
|
||||||
fext
|
fext
|
||||||
fgetattr
|
fgetattr
|
||||||
|
fgetattr_impl
|
||||||
filebase
|
filebase
|
||||||
flac_version
|
flac_version
|
||||||
flag_nopath
|
flag_nopath
|
||||||
@ -117,6 +120,7 @@ icui18n
|
|||||||
icuuc
|
icuuc
|
||||||
iostreams
|
iostreams
|
||||||
iphlpapi
|
iphlpapi
|
||||||
|
jthread
|
||||||
libbitcoin
|
libbitcoin
|
||||||
libbitcoinsystem
|
libbitcoinsystem
|
||||||
libcurl
|
libcurl
|
||||||
@ -135,6 +139,8 @@ libuuid
|
|||||||
libuuid_include_dirs
|
libuuid_include_dirs
|
||||||
libvlc
|
libvlc
|
||||||
linkflags
|
linkflags
|
||||||
|
lptr
|
||||||
|
lpwstr
|
||||||
markdownlint
|
markdownlint
|
||||||
mbig
|
mbig
|
||||||
msvc
|
msvc
|
||||||
@ -153,7 +159,9 @@ oleaut32
|
|||||||
openal_version
|
openal_version
|
||||||
openssldir
|
openssldir
|
||||||
pkgconfig
|
pkgconfig
|
||||||
|
plarge_integer
|
||||||
plex
|
plex
|
||||||
|
println
|
||||||
project_enable_fontconfig
|
project_enable_fontconfig
|
||||||
project_enable_gtkmm
|
project_enable_gtkmm
|
||||||
project_enable_libdsm
|
project_enable_libdsm
|
||||||
@ -165,6 +173,7 @@ pugixml_project
|
|||||||
puint32
|
puint32
|
||||||
pvoid
|
pvoid
|
||||||
pwstr
|
pwstr
|
||||||
|
rdrw
|
||||||
remote_winfsp
|
remote_winfsp
|
||||||
renterd
|
renterd
|
||||||
richtext
|
richtext
|
||||||
|
13
CHANGELOG.md
13
CHANGELOG.md
@ -2,10 +2,14 @@
|
|||||||
|
|
||||||
## v2.0.2-rc
|
## v2.0.2-rc
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* Refactored `config.json` - will need to verify configuration settings prior to mounting
|
||||||
|
|
||||||
### Issues
|
### Issues
|
||||||
|
|
||||||
* \#12 \[Unit Test\] Complete all providers unit tests
|
* \#12 \[Unit Test\] Complete all providers unit tests
|
||||||
* \#14 \[Unit Test \] SQLite mini-ORM unit tests and cleanup
|
* \#14 \[Unit Test\] SQLite mini-ORM unit tests and cleanup
|
||||||
* \#16 Add support for bucket name in Sia provider
|
* \#16 Add support for bucket name in Sia provider
|
||||||
* \#17 Update to common c++ build system
|
* \#17 Update to common c++ build system
|
||||||
* A single 64-bit Linux Jenkins server is used to build all Linux and Windows versions
|
* A single 64-bit Linux Jenkins server is used to build all Linux and Windows versions
|
||||||
@ -14,11 +18,18 @@
|
|||||||
* MSYS2 is required for building Windows binaries on Windows
|
* MSYS2 is required for building Windows binaries on Windows
|
||||||
* OS X support is temporarily disabled
|
* OS X support is temporarily disabled
|
||||||
* \#19 \[bug\] Rename file is broken for files that are existing
|
* \#19 \[bug\] Rename file is broken for files that are existing
|
||||||
|
* \#23 \[bug\] Incorrect file size displayed while upload is pending
|
||||||
|
* \#24 RocksDB implementations should be transactional
|
||||||
|
* \#25 Writes should block when maximum cache size is reached
|
||||||
|
* \#26 Complete ring buffer and direct download support
|
||||||
|
|
||||||
### Changes from v2.0.1-rc
|
### Changes from v2.0.1-rc
|
||||||
|
|
||||||
|
* Ability to choose between RocksDB and SQLite databases
|
||||||
|
* Added direct reads and implemented download fallback
|
||||||
* Corrected file times on S3 and Sia providers
|
* Corrected file times on S3 and Sia providers
|
||||||
* Corrected handling of `chown()` and `chmod()`
|
* Corrected handling of `chown()` and `chmod()`
|
||||||
|
* Fixed erroneous download of chunks after resize
|
||||||
|
|
||||||
## v2.0.1-rc
|
## v2.0.1-rc
|
||||||
|
|
||||||
|
@ -148,6 +148,7 @@ endif()
|
|||||||
-DPROJECT_ENABLE_LIBSODIUM=${PROJECT_ENABLE_LIBSODIUM}
|
-DPROJECT_ENABLE_LIBSODIUM=${PROJECT_ENABLE_LIBSODIUM}
|
||||||
-DPROJECT_ENABLE_OPENSSL=${PROJECT_ENABLE_OPENSSL}
|
-DPROJECT_ENABLE_OPENSSL=${PROJECT_ENABLE_OPENSSL}
|
||||||
-DPROJECT_ENABLE_PUGIXML=${PROJECT_ENABLE_PUGIXML}
|
-DPROJECT_ENABLE_PUGIXML=${PROJECT_ENABLE_PUGIXML}
|
||||||
|
-DPROJECT_ENABLE_ROCKSDB=${PROJECT_ENABLE_ROCKSDB}
|
||||||
-DPROJECT_ENABLE_SPDLOG=${PROJECT_ENABLE_SPDLOG}
|
-DPROJECT_ENABLE_SPDLOG=${PROJECT_ENABLE_SPDLOG}
|
||||||
-DPROJECT_ENABLE_SQLITE=${PROJECT_ENABLE_SQLITE}
|
-DPROJECT_ENABLE_SQLITE=${PROJECT_ENABLE_SQLITE}
|
||||||
-DPROJECT_ENABLE_STDUUID=${PROJECT_ENABLE_STDUUID}
|
-DPROJECT_ENABLE_STDUUID=${PROJECT_ENABLE_STDUUID}
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
set(BINUTILS_HASH ae9a5789e23459e59606e6714723f2d3ffc31c03174191ef0d015bdf06007450)
|
set(BINUTILS_HASH ae9a5789e23459e59606e6714723f2d3ffc31c03174191ef0d015bdf06007450)
|
||||||
|
set(BOOST_HASH f55c340aa49763b1925ccf02b2e83f35fdcf634c9d5164a2acb87540173c741d)
|
||||||
set(BOOST2_HASH 7bd7ddceec1a1dfdcbdb3e609b60d01739c38390a5f956385a12f3122049f0ca)
|
set(BOOST2_HASH 7bd7ddceec1a1dfdcbdb3e609b60d01739c38390a5f956385a12f3122049f0ca)
|
||||||
set(BOOST_HASH be0d91732d5b0cc6fbb275c7939974457e79b54d6f07ce2e3dfdd68bef883b0b)
|
set(CPP_HTTPLIB_HASH 405abd8170f2a446fc8612ac635d0db5947c0d2e156e32603403a4496255ff00)
|
||||||
set(CPP_HTTPLIB_HASH c1742fc7179aaae2a67ad9bba0740b7e9ffaf4f5e62feef53101ecdef1478716)
|
set(CURL_HASH 5a231145114589491fc52da118f9c7ef8abee885d1cb1ced99c7290e9a352f07)
|
||||||
set(CURL_HASH d714818f6ac41ae9154850158fed44b7a87650a6d52f83d3bcb9aa527be354d7)
|
set(EXPAT_HASH 372b18f6527d162fa9658f1c74d22a37429b82d822f5a1e1fc7e00f6045a06a2)
|
||||||
set(EXPAT_HASH fbd032683370d761ba68dba2566d3280a154f5290634172d60a79b24d366d9dc)
|
|
||||||
set(GCC_HASH 7d376d445f93126dc545e2c0086d0f647c3094aae081cdb78f42ce2bc25e7293)
|
set(GCC_HASH 7d376d445f93126dc545e2c0086d0f647c3094aae081cdb78f42ce2bc25e7293)
|
||||||
set(GTEST_HASH 7b42b4d6ed48810c5362c265a17faebe90dc2373c885e5216439d37927f02926)
|
set(GTEST_HASH 7b42b4d6ed48810c5362c265a17faebe90dc2373c885e5216439d37927f02926)
|
||||||
set(ICU_HASH 925e6b4b8cf8856e0ac214f6f34e30dee63b7bb7a50460ab4603950eff48f89e)
|
set(ICU_HASH 925e6b4b8cf8856e0ac214f6f34e30dee63b7bb7a50460ab4603950eff48f89e)
|
||||||
set(JSON_HASH 0d8ef5af7f9794e3263480193c491549b2ba6cc74bb018906202ada498a79406)
|
set(JSON_HASH 0d8ef5af7f9794e3263480193c491549b2ba6cc74bb018906202ada498a79406)
|
||||||
set(LIBSODIUM_HASH 8e5aeca07a723a27bbecc3beef14b0068d37e7fc0e97f51b3f1c82d2a58005c1)
|
set(LIBSODIUM_HASH 8e5aeca07a723a27bbecc3beef14b0068d37e7fc0e97f51b3f1c82d2a58005c1)
|
||||||
set(MINGW_HASH 3f66bce069ee8bed7439a1a13da7cb91a5e67ea6170f21317ac7f5794625ee10)
|
set(MINGW_HASH 3f66bce069ee8bed7439a1a13da7cb91a5e67ea6170f21317ac7f5794625ee10)
|
||||||
set(OPENSSL_HASH 777cd596284c883375a2a7a11bf5d2786fc5413255efab20c50d6ffe6d020b7e)
|
set(OPENSSL_HASH e15dda82fe2fe8139dc2ac21a36d4ca01d5313c75f99f46c4e8a27709b7294bf)
|
||||||
set(PKG_CONFIG_HASH 6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591)
|
set(PKG_CONFIG_HASH 6fc69c01688c9458a57eb9a1664c9aba372ccda420a02bf4429fe610e7e7d591)
|
||||||
set(PUGIXML_HASH 2f10e276870c64b1db6809050a75e11a897a8d7456c4be5c6b2e35a11168a015)
|
set(PUGIXML_HASH 2f10e276870c64b1db6809050a75e11a897a8d7456c4be5c6b2e35a11168a015)
|
||||||
set(SPDLOG_HASH 1586508029a7d0670dfcb2d97575dcdc242d3868a259742b69f100801ab4e16b)
|
set(ROCKSDB_HASH 9b810c81731835fda0d4bbdb51d3199d901fa4395733ab63752d297da84c5a47)
|
||||||
|
set(SPDLOG_HASH 9962648c9b4f1a7bbc76fd8d9172555bad1871fdb14ff4f842ef87949682caa5)
|
||||||
set(SQLITE_HASH 77823cb110929c2bcb0f5d48e4833b5c59a8a6e40cdea3936b99e199dbbe5784)
|
set(SQLITE_HASH 77823cb110929c2bcb0f5d48e4833b5c59a8a6e40cdea3936b99e199dbbe5784)
|
||||||
set(STDUUID_HASH b1176597e789531c38481acbbed2a6894ad419aab0979c10410d59eb0ebf40d3)
|
set(STDUUID_HASH b1176597e789531c38481acbbed2a6894ad419aab0979c10410d59eb0ebf40d3)
|
||||||
set(ZLIB_HASH 17e88863f3600672ab49182f217281b6fc4d3c762bde361935e436a95214d05c)
|
set(ZLIB_HASH 17e88863f3600672ab49182f217281b6fc4d3c762bde361935e436a95214d05c)
|
||||||
|
@ -17,6 +17,7 @@ include(cmake/libraries/fuse.cmake)
|
|||||||
include(cmake/libraries/json.cmake)
|
include(cmake/libraries/json.cmake)
|
||||||
include(cmake/libraries/libsodium.cmake)
|
include(cmake/libraries/libsodium.cmake)
|
||||||
include(cmake/libraries/pugixml.cmake)
|
include(cmake/libraries/pugixml.cmake)
|
||||||
|
include(cmake/libraries/rocksdb.cmake)
|
||||||
include(cmake/libraries/spdlog.cmake)
|
include(cmake/libraries/spdlog.cmake)
|
||||||
include(cmake/libraries/sqlite.cmake)
|
include(cmake/libraries/sqlite.cmake)
|
||||||
include(cmake/libraries/stduuid.cmake)
|
include(cmake/libraries/stduuid.cmake)
|
||||||
|
34
cmake/libraries/rocksdb.cmake
Normal file
34
cmake/libraries/rocksdb.cmake
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
if(PROJECT_ENABLE_ROCKSDB)
|
||||||
|
if(PROJECT_BUILD)
|
||||||
|
add_definitions(-DPROJECT_ENABLE_ROCKSDB)
|
||||||
|
find_library(ROCKSDB_LIBRARY NAMES librocksdb.a REQUIRED)
|
||||||
|
link_libraries(${ROCKSDB_LIBRARY})
|
||||||
|
elseif(NOT PROJECT_IS_MINGW OR CMAKE_HOST_WIN32)
|
||||||
|
ExternalProject_Add(rocksdb_project
|
||||||
|
PREFIX external
|
||||||
|
URL ${PROJECT_3RD_PARTY_DIR}/rocksdb-${ROCKSDB_VERSION}.tar.gz
|
||||||
|
URL_HASH SHA256=${ROCKSDB_HASH}
|
||||||
|
LIST_SEPARATOR |
|
||||||
|
CMAKE_ARGS ${PROJECT_EXTERNAL_CMAKE_FLAGS}
|
||||||
|
-DBUILD_SHARED_LIBS=OFF
|
||||||
|
-DBUILD_STATIC_LIBS=ON
|
||||||
|
-DFAIL_ON_WARNINGS=OFF
|
||||||
|
-DPORTABLE=1
|
||||||
|
-DROCKSDB_BUILD_SHARED=OFF
|
||||||
|
-DROCKSDB_INSTALL_ON_WINDOWS=ON
|
||||||
|
-DWITH_BENCHMARK=OFF
|
||||||
|
-DWITH_BENCHMARK_TOOLS=OFF
|
||||||
|
-DWITH_CORE_TOOLS=OFF
|
||||||
|
-DWITH_EXAMPLES=OFF
|
||||||
|
-DWITH_GFLAGS=OFF
|
||||||
|
-DWITH_IOSTATS_CONTEXT=OFF
|
||||||
|
-DWITH_PERF_CONTEXT=OFF
|
||||||
|
-DWITH_TESTS=OFF
|
||||||
|
-DWITH_TOOLS=OFF
|
||||||
|
-DWITH_TRACE_TOOLS=OFF
|
||||||
|
-DWITH_ZLIB=ON
|
||||||
|
)
|
||||||
|
|
||||||
|
list(APPEND PROJECT_DEPENDENCIES rocksdb_project)
|
||||||
|
endif()
|
||||||
|
endif()
|
@ -6,6 +6,7 @@ option(PROJECT_ENABLE_JSON "Enable JSON for Modern C++ library" ON)
|
|||||||
option(PROJECT_ENABLE_LIBSODIUM "Enable libsodium library" ON)
|
option(PROJECT_ENABLE_LIBSODIUM "Enable libsodium library" ON)
|
||||||
option(PROJECT_ENABLE_OPENSSL "Enable OpenSSL library" ON)
|
option(PROJECT_ENABLE_OPENSSL "Enable OpenSSL library" ON)
|
||||||
option(PROJECT_ENABLE_PUGIXML "Enable PugiXML library" ON)
|
option(PROJECT_ENABLE_PUGIXML "Enable PugiXML library" ON)
|
||||||
|
option(PROJECT_ENABLE_ROCKSDB "Enable RocksDB library" ON)
|
||||||
option(PROJECT_ENABLE_SPDLOG "Enable spdlog library" ON)
|
option(PROJECT_ENABLE_SPDLOG "Enable spdlog library" ON)
|
||||||
option(PROJECT_ENABLE_SQLITE "Enable SQLite" ON)
|
option(PROJECT_ENABLE_SQLITE "Enable SQLite" ON)
|
||||||
option(PROJECT_ENABLE_STDUUID "Enable stduuid library" ON)
|
option(PROJECT_ENABLE_STDUUID "Enable stduuid library" ON)
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
set(BINUTILS_VERSION 2.41)
|
set(BINUTILS_VERSION 2.41)
|
||||||
set(BOOST_MAJOR_VERSION 1)
|
|
||||||
set(BOOST_MINOR_VERSION 85)
|
|
||||||
set(BOOST_PATCH_VERSION 0)
|
|
||||||
set(BOOST2_MAJOR_VERSION 1)
|
set(BOOST2_MAJOR_VERSION 1)
|
||||||
set(BOOST2_MINOR_VERSION 76)
|
set(BOOST2_MINOR_VERSION 76)
|
||||||
set(BOOST2_PATCH_VERSION 0)
|
set(BOOST2_PATCH_VERSION 0)
|
||||||
set(CPP_HTTPLIB_VERSION 0.16.3)
|
set(BOOST_MAJOR_VERSION 1)
|
||||||
set(CURL_VERSION 8.9.1)
|
set(BOOST_MINOR_VERSION 87)
|
||||||
set(CURL2_VERSION 8_9_1)
|
set(BOOST_PATCH_VERSION 0)
|
||||||
set(EXPAT_VERSION 2.6.2)
|
set(CPP_HTTPLIB_VERSION 0.18.1)
|
||||||
set(EXPAT2_VERSION 2_6_2)
|
set(CURL2_VERSION 8_11_0)
|
||||||
|
set(CURL_VERSION 8.11.0)
|
||||||
|
set(EXPAT2_VERSION 2_6_4)
|
||||||
|
set(EXPAT_VERSION 2.6.4)
|
||||||
set(GCC_VERSION 14.2.0)
|
set(GCC_VERSION 14.2.0)
|
||||||
set(GTEST_VERSION 1.15.2)
|
set(GTEST_VERSION 1.15.2)
|
||||||
set(ICU_VERSION 75-1)
|
set(ICU_VERSION 75-1)
|
||||||
@ -17,11 +17,12 @@ set(JSON_VERSION 3.11.3)
|
|||||||
set(LIBSODIUM_VERSION 1.0.20)
|
set(LIBSODIUM_VERSION 1.0.20)
|
||||||
set(MESA_VERSION 23.3.3)
|
set(MESA_VERSION 23.3.3)
|
||||||
set(MINGW_VERSION 11.0.1)
|
set(MINGW_VERSION 11.0.1)
|
||||||
set(OPENSSL_VERSION 3.3.1)
|
set(OPENSSL_VERSION 3.4.0)
|
||||||
set(PKG_CONFIG_VERSION 0.29.2)
|
set(PKG_CONFIG_VERSION 0.29.2)
|
||||||
set(PUGIXML_VERSION 1.14)
|
set(PUGIXML_VERSION 1.14)
|
||||||
set(SPDLOG_VERSION 1.14.1)
|
set(ROCKSDB_VERSION 9.7.4)
|
||||||
set(SQLITE_VERSION 3460100)
|
set(SPDLOG_VERSION 1.15.0)
|
||||||
set(SQLITE2_VERSION 3.46.1)
|
set(SQLITE2_VERSION 3.46.1)
|
||||||
|
set(SQLITE_VERSION 3460100)
|
||||||
set(STDUUID_VERSION 1.2.3)
|
set(STDUUID_VERSION 1.2.3)
|
||||||
set(ZLIB_VERSION 1.3.1)
|
set(ZLIB_VERSION 1.3.1)
|
||||||
|
@ -30,6 +30,7 @@ PROJECT_ENABLE_JSON=ON
|
|||||||
PROJECT_ENABLE_LIBSODIUM=ON
|
PROJECT_ENABLE_LIBSODIUM=ON
|
||||||
PROJECT_ENABLE_OPENSSL=ON
|
PROJECT_ENABLE_OPENSSL=ON
|
||||||
PROJECT_ENABLE_PUGIXML=ON
|
PROJECT_ENABLE_PUGIXML=ON
|
||||||
|
PROJECT_ENABLE_ROCKSDB=ON
|
||||||
PROJECT_ENABLE_SPDLOG=ON
|
PROJECT_ENABLE_SPDLOG=ON
|
||||||
PROJECT_ENABLE_SQLITE=ON
|
PROJECT_ENABLE_SQLITE=ON
|
||||||
PROJECT_ENABLE_STDUUID=ON
|
PROJECT_ENABLE_STDUUID=ON
|
||||||
|
@ -604,6 +604,7 @@ RUN if [ -f "/3rd_party/SFML-${MY_SFML_VERSION}.tar.gz" ]; then \
|
|||||||
-DBUILD_STATIC_LIBS=ON \
|
-DBUILD_STATIC_LIBS=ON \
|
||||||
-DCMAKE_CXX_STANDARD=${MY_CXX_STANDARD} \
|
-DCMAKE_CXX_STANDARD=${MY_CXX_STANDARD} \
|
||||||
-DCMAKE_INSTALL_PREFIX=${MY_MINGW_DIR} \
|
-DCMAKE_INSTALL_PREFIX=${MY_MINGW_DIR} \
|
||||||
|
-DCMAKE_SYSTEM_PROCESSOR=AMD64 \
|
||||||
-DCMAKE_TOOLCHAIN_FILE=${MY_TOOLCHAIN_FILE_CMAKE} \
|
-DCMAKE_TOOLCHAIN_FILE=${MY_TOOLCHAIN_FILE_CMAKE} \
|
||||||
&& make -j${MY_NUM_JOBS} \
|
&& make -j${MY_NUM_JOBS} \
|
||||||
&& make install \
|
&& make install \
|
||||||
|
@ -22,432 +22,233 @@
|
|||||||
#ifndef REPERTORY_INCLUDE_APP_CONFIG_HPP_
|
#ifndef REPERTORY_INCLUDE_APP_CONFIG_HPP_
|
||||||
#define REPERTORY_INCLUDE_APP_CONFIG_HPP_
|
#define REPERTORY_INCLUDE_APP_CONFIG_HPP_
|
||||||
|
|
||||||
#include "events/event_system.hpp"
|
#include "events/event.hpp"
|
||||||
#include "events/events.hpp"
|
#include "types/remote.hpp"
|
||||||
#include "types/repertory.hpp"
|
#include "types/repertory.hpp"
|
||||||
#include "utils/error_utils.hpp"
|
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
class app_config final {
|
class app_config final {
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] static auto default_agent_name(const provider_type &prov)
|
[[nodiscard]] static auto
|
||||||
-> std::string;
|
default_agent_name(const provider_type &prov) -> std::string;
|
||||||
|
|
||||||
[[nodiscard]] static auto default_api_port(const provider_type &prov)
|
[[nodiscard]] static auto
|
||||||
-> std::uint16_t;
|
default_api_port(const provider_type &prov) -> std::uint16_t;
|
||||||
|
|
||||||
[[nodiscard]] static auto default_data_directory(const provider_type &prov)
|
[[nodiscard]] static auto
|
||||||
-> std::string;
|
default_data_directory(const provider_type &prov) -> std::string;
|
||||||
|
|
||||||
[[nodiscard]] static auto default_remote_port(const provider_type &prov)
|
[[nodiscard]] static auto
|
||||||
-> std::uint16_t;
|
default_remote_api_port(const provider_type &prov) -> std::uint16_t;
|
||||||
|
|
||||||
[[nodiscard]] static auto default_rpc_port(const provider_type &prov)
|
[[nodiscard]] static auto
|
||||||
-> std::uint16_t;
|
default_rpc_port(const provider_type &prov) -> std::uint16_t;
|
||||||
|
|
||||||
[[nodiscard]] static auto get_provider_display_name(const provider_type &prov)
|
[[nodiscard]] static auto
|
||||||
-> std::string;
|
get_provider_display_name(const provider_type &prov) -> std::string;
|
||||||
|
|
||||||
[[nodiscard]] static auto get_provider_name(const provider_type &prov)
|
[[nodiscard]] static auto
|
||||||
-> std::string;
|
get_provider_name(const provider_type &prov) -> std::string;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
app_config(const provider_type &prov, std::string_view data_directory = "");
|
app_config(const provider_type &prov, std::string_view data_directory = "");
|
||||||
|
|
||||||
|
app_config() = delete;
|
||||||
|
app_config(app_config &&) = delete;
|
||||||
|
app_config(const app_config &) = delete;
|
||||||
|
|
||||||
~app_config() { save(); }
|
~app_config() { save(); }
|
||||||
|
|
||||||
|
auto operator=(const app_config &) -> app_config & = delete;
|
||||||
|
auto operator=(app_config &&) -> app_config & = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
provider_type prov_;
|
provider_type prov_;
|
||||||
std::string api_auth_;
|
atomic<std::string> api_auth_;
|
||||||
std::uint16_t api_port_;
|
std::atomic<std::uint16_t> api_port_;
|
||||||
std::string api_user_;
|
atomic<std::string> api_user_;
|
||||||
bool config_changed_;
|
std::atomic<bool> config_changed_;
|
||||||
std::string data_directory_;
|
std::atomic<database_type> db_type_{database_type::rocksdb};
|
||||||
std::uint8_t download_timeout_secs_;
|
std::atomic<std::uint8_t> download_timeout_secs_;
|
||||||
bool enable_chunk_downloader_timeout_;
|
std::atomic<bool> enable_download_timeout_;
|
||||||
bool enable_comm_duration_events_;
|
std::atomic<bool> enable_drive_events_;
|
||||||
bool enable_drive_events_;
|
|
||||||
bool enable_max_cache_size_;
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
bool enable_mount_manager_;
|
std::atomic<bool> enable_mount_manager_;
|
||||||
#endif // defined(_WIN32)
|
#endif // defined(_WIN32)
|
||||||
bool enable_remote_mount_;
|
std::atomic<event_level> event_level_;
|
||||||
encrypt_config encrypt_config_;
|
std::atomic<std::uint32_t> eviction_delay_mins_;
|
||||||
event_level event_level_;
|
std::atomic<bool> eviction_uses_accessed_time_;
|
||||||
std::uint32_t eviction_delay_mins_;
|
std::atomic<std::uint16_t> high_freq_interval_secs_;
|
||||||
bool eviction_uses_accessed_time_;
|
std::atomic<std::uint16_t> low_freq_interval_secs_;
|
||||||
std::uint8_t high_freq_interval_secs_;
|
std::atomic<std::uint64_t> max_cache_size_bytes_;
|
||||||
bool is_remote_mount_;
|
std::atomic<std::uint8_t> max_upload_count_;
|
||||||
std::uint32_t low_freq_interval_secs_;
|
std::atomic<std::uint16_t> med_freq_interval_secs_;
|
||||||
std::uint64_t max_cache_size_bytes_;
|
std::atomic<std::uint16_t> online_check_retry_secs_;
|
||||||
std::uint8_t max_upload_count_;
|
std::atomic<std::uint16_t> orphaned_file_retention_days_;
|
||||||
std::uint8_t min_download_timeout_secs_;
|
std::atomic<download_type> preferred_download_type_;
|
||||||
std::uint16_t online_check_retry_secs_;
|
std::atomic<std::uint16_t> retry_read_count_;
|
||||||
std::uint16_t orphaned_file_retention_days_;
|
std::atomic<std::uint16_t> ring_buffer_file_size_;
|
||||||
std::string preferred_download_type_;
|
std::atomic<std::uint16_t> task_wait_ms_;
|
||||||
std::uint8_t read_ahead_count_;
|
|
||||||
std::uint8_t remote_client_pool_size_;
|
private:
|
||||||
std::string remote_host_name_or_ip_;
|
|
||||||
std::uint8_t remote_max_connections_;
|
|
||||||
std::uint16_t remote_port_;
|
|
||||||
std::uint16_t remote_receive_timeout_secs_;
|
|
||||||
std::uint16_t remote_send_timeout_secs_;
|
|
||||||
std::string remote_token_;
|
|
||||||
std::uint16_t retry_read_count_;
|
|
||||||
std::uint16_t ring_buffer_file_size_;
|
|
||||||
std::string cache_directory_;
|
std::string cache_directory_;
|
||||||
host_config hc_;
|
std::string data_directory_;
|
||||||
s3_config s3_config_;
|
atomic<encrypt_config> encrypt_config_;
|
||||||
sia_config sia_config_{};
|
atomic<host_config> host_config_;
|
||||||
std::uint64_t version_{REPERTORY_CONFIG_VERSION};
|
|
||||||
std::string log_directory_;
|
std::string log_directory_;
|
||||||
mutable std::recursive_mutex read_write_mutex_;
|
mutable std::recursive_mutex read_write_mutex_;
|
||||||
mutable std::recursive_mutex remote_mount_mutex_;
|
atomic<remote::remote_config> remote_config_;
|
||||||
|
atomic<remote::remote_mount> remote_mount_;
|
||||||
|
atomic<s3_config> s3_config_;
|
||||||
|
atomic<sia_config> sia_config_;
|
||||||
|
std::unordered_map<std::string, std::function<std::string()>>
|
||||||
|
value_get_lookup_;
|
||||||
|
std::unordered_map<std::string,
|
||||||
|
std::function<std::string(const std::string &)>>
|
||||||
|
value_set_lookup_;
|
||||||
|
std::uint64_t version_{REPERTORY_CONFIG_VERSION};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] auto load() -> bool;
|
[[nodiscard]] auto load() -> bool;
|
||||||
|
|
||||||
template <typename dest>
|
|
||||||
auto get_value(const json &json_document, const std::string &name, dest &dst,
|
|
||||||
bool &success_flag) -> bool {
|
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
|
||||||
|
|
||||||
auto ret{false};
|
|
||||||
try {
|
|
||||||
if (json_document.find(name) != json_document.end()) {
|
|
||||||
dst = json_document[name].get<dest>();
|
|
||||||
ret = true;
|
|
||||||
} else {
|
|
||||||
success_flag = false;
|
|
||||||
}
|
|
||||||
} catch (const json::exception &ex) {
|
|
||||||
utils::error::raise_error(function_name, ex, "exception occurred");
|
|
||||||
success_flag = false;
|
|
||||||
ret = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename dest, typename source>
|
template <typename dest, typename source>
|
||||||
auto set_value(dest &dst, const source &src) -> bool {
|
auto set_value(dest &dst, const source &src) -> bool;
|
||||||
auto ret{false};
|
|
||||||
recur_mutex_lock lock(read_write_mutex_);
|
|
||||||
if (dst != src) {
|
|
||||||
dst = src;
|
|
||||||
config_changed_ = true;
|
|
||||||
save();
|
|
||||||
ret = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] auto get_api_auth() const -> std::string { return api_auth_; }
|
[[nodiscard]] auto get_api_auth() const -> std::string;
|
||||||
|
|
||||||
[[nodiscard]] auto get_api_port() const -> std::uint16_t { return api_port_; }
|
[[nodiscard]] auto get_api_port() const -> std::uint16_t;
|
||||||
|
|
||||||
[[nodiscard]] auto get_api_user() const -> std::string { return api_user_; }
|
[[nodiscard]] auto get_api_user() const -> std::string;
|
||||||
|
|
||||||
[[nodiscard]] auto get_cache_directory() const -> std::string {
|
[[nodiscard]] auto get_cache_directory() const -> std::string;
|
||||||
return cache_directory_;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_chunk_downloader_timeout_secs() const -> std::uint8_t {
|
|
||||||
return std::max(min_download_timeout_secs_, download_timeout_secs_);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_config_file_path() const -> std::string;
|
[[nodiscard]] auto get_config_file_path() const -> std::string;
|
||||||
|
|
||||||
[[nodiscard]] auto get_data_directory() const -> std::string {
|
[[nodiscard]] auto get_database_type() const -> database_type;
|
||||||
return data_directory_;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_enable_chunk_download_timeout() const -> bool {
|
[[nodiscard]] auto get_data_directory() const -> std::string;
|
||||||
return enable_chunk_downloader_timeout_;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_enable_comm_duration_events() const -> bool {
|
[[nodiscard]] auto get_download_timeout_secs() const -> std::uint8_t;
|
||||||
return enable_comm_duration_events_;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_enable_drive_events() const -> bool {
|
[[nodiscard]] auto get_enable_download_timeout() const -> bool;
|
||||||
return enable_drive_events_;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_encrypt_config() const -> encrypt_config {
|
[[nodiscard]] auto get_enable_drive_events() const -> bool;
|
||||||
return encrypt_config_;
|
|
||||||
}
|
[[nodiscard]] auto get_encrypt_config() const -> encrypt_config;
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
[[nodiscard]] auto get_enable_mount_manager() const -> bool {
|
[[nodiscard]] auto get_enable_mount_manager() const -> bool;
|
||||||
return enable_mount_manager_;
|
#endif // defined(_WIN32)
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_enable_max_cache_size() const -> bool {
|
[[nodiscard]] auto get_event_level() const -> event_level;
|
||||||
return enable_max_cache_size_;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_enable_remote_mount() const -> bool {
|
[[nodiscard]] auto get_eviction_delay_mins() const -> std::uint32_t;
|
||||||
return enable_remote_mount_;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_event_level() const -> event_level {
|
[[nodiscard]] auto get_eviction_uses_accessed_time() const -> bool;
|
||||||
return event_level_;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_eviction_delay_mins() const -> std::uint32_t {
|
[[nodiscard]] auto get_high_frequency_interval_secs() const -> std::uint16_t;
|
||||||
return eviction_delay_mins_;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_eviction_uses_accessed_time() const -> bool {
|
[[nodiscard]] auto get_host_config() const -> host_config;
|
||||||
return eviction_uses_accessed_time_;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_high_frequency_interval_secs() const -> std::uint8_t {
|
|
||||||
return std::max(static_cast<std::uint8_t>(1U), high_freq_interval_secs_);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_host_config() const -> host_config { return hc_; }
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_is_remote_mount() const -> bool {
|
|
||||||
return is_remote_mount_;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_json() const -> json;
|
[[nodiscard]] auto get_json() const -> json;
|
||||||
|
|
||||||
[[nodiscard]] auto get_log_directory() const -> std::string {
|
[[nodiscard]] auto get_log_directory() const -> std::string;
|
||||||
return log_directory_;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_low_frequency_interval_secs() const -> std::uint32_t {
|
[[nodiscard]] auto get_low_frequency_interval_secs() const -> std::uint16_t;
|
||||||
return std::max(1U, low_freq_interval_secs_);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_max_cache_size_bytes() const -> std::uint64_t;
|
[[nodiscard]] auto get_max_cache_size_bytes() const -> std::uint64_t;
|
||||||
|
|
||||||
[[nodiscard]] auto get_max_upload_count() const -> std::uint8_t {
|
[[nodiscard]] auto get_max_upload_count() const -> std::uint8_t;
|
||||||
return std::max(std::uint8_t(1U), max_upload_count_);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_online_check_retry_secs() const -> std::uint16_t {
|
[[nodiscard]] auto get_med_frequency_interval_secs() const -> std::uint16_t;
|
||||||
return std::max(std::uint16_t(15U), online_check_retry_secs_);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_orphaned_file_retention_days() const -> std::uint16_t {
|
[[nodiscard]] auto get_online_check_retry_secs() const -> std::uint16_t;
|
||||||
return std::min(static_cast<std::uint16_t>(31U),
|
|
||||||
std::max(static_cast<std::uint16_t>(1U),
|
|
||||||
orphaned_file_retention_days_));
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_preferred_download_type() const -> download_type {
|
[[nodiscard]] auto get_orphaned_file_retention_days() const -> std::uint16_t;
|
||||||
return download_type_from_string(preferred_download_type_,
|
|
||||||
download_type::fallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_provider_type() const -> provider_type {
|
[[nodiscard]] auto get_preferred_download_type() const -> download_type;
|
||||||
return prov_;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_read_ahead_count() const -> std::uint8_t {
|
[[nodiscard]] auto get_provider_type() const -> provider_type;
|
||||||
return std::max(static_cast<std::uint8_t>(1U), read_ahead_count_);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_remote_client_pool_size() const -> std::uint8_t {
|
[[nodiscard]] auto get_remote_config() const -> remote::remote_config;
|
||||||
return std::max(static_cast<std::uint8_t>(5U), remote_client_pool_size_);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_remote_host_name_or_ip() const -> std::string {
|
[[nodiscard]] auto get_remote_mount() const -> remote::remote_mount;
|
||||||
return remote_host_name_or_ip_;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_remote_max_connections() const -> std::uint8_t {
|
[[nodiscard]] auto get_retry_read_count() const -> std::uint16_t;
|
||||||
return std::max(static_cast<std::uint8_t>(1U), remote_max_connections_);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_remote_port() const -> std::uint16_t {
|
[[nodiscard]] auto get_ring_buffer_file_size() const -> std::uint16_t;
|
||||||
return remote_port_;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_remote_receive_timeout_secs() const -> std::uint16_t {
|
[[nodiscard]] auto get_s3_config() const -> s3_config;
|
||||||
return remote_receive_timeout_secs_;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_remote_send_timeout_secs() const -> std::uint16_t {
|
[[nodiscard]] auto get_sia_config() const -> sia_config;
|
||||||
return remote_send_timeout_secs_;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_remote_token() const -> std::string {
|
[[nodiscard]] auto get_task_wait_ms() const -> std::uint16_t;
|
||||||
return remote_token_;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_retry_read_count() const -> std::uint16_t {
|
[[nodiscard]] auto
|
||||||
return std::max(std::uint16_t(2), retry_read_count_);
|
get_value_by_name(const std::string &name) const -> std::string;
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_ring_buffer_file_size() const -> std::uint16_t {
|
[[nodiscard]] auto get_version() const -> std::uint64_t;
|
||||||
return std::max(
|
|
||||||
static_cast<std::uint16_t>(64U),
|
|
||||||
std::min(static_cast<std::uint16_t>(1024U), ring_buffer_file_size_));
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_s3_config() const -> s3_config { return s3_config_; }
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_sia_config() const -> sia_config {
|
|
||||||
return sia_config_;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_value_by_name(const std::string &name) -> std::string;
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_version() const -> std::uint64_t { return version_; }
|
|
||||||
|
|
||||||
void save();
|
void save();
|
||||||
|
|
||||||
void set_api_auth(const std::string &api_auth) {
|
void set_api_auth(const std::string &value);
|
||||||
set_value(api_auth_, api_auth);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_api_port(std::uint16_t api_port) { set_value(api_port_, api_port); }
|
void set_api_port(std::uint16_t value);
|
||||||
|
|
||||||
void set_api_user(const std::string &api_user) {
|
void set_api_user(const std::string &value);
|
||||||
set_value(api_user_, api_user);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_chunk_downloader_timeout_secs(
|
void set_download_timeout_secs(std::uint8_t value);
|
||||||
std::uint8_t chunk_downloader_timeout_secs) {
|
|
||||||
set_value(download_timeout_secs_, chunk_downloader_timeout_secs);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void set_database_type(const database_type &value);
|
||||||
set_enable_chunk_downloader_timeout(bool enable_chunk_downloader_timeout) {
|
|
||||||
set_value(enable_chunk_downloader_timeout_,
|
|
||||||
enable_chunk_downloader_timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_enable_comm_duration_events(bool enable_comm_duration_events) {
|
void set_enable_download_timeout(bool value);
|
||||||
set_value(enable_comm_duration_events_, enable_comm_duration_events);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_enable_drive_events(bool enable_drive_events) {
|
void set_enable_drive_events(bool value);
|
||||||
set_value(enable_drive_events_, enable_drive_events);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_enable_max_cache_size(bool enable_max_cache_size) {
|
|
||||||
set_value(enable_max_cache_size_, enable_max_cache_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
void set_enable_mount_manager(bool enable_mount_manager) {
|
void set_enable_mount_manager(bool value);
|
||||||
set_value(enable_mount_manager_, enable_mount_manager);
|
#endif // defined(_WIN32)
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void set_enable_remote_mount(bool enable_remote_mount);
|
void set_event_level(const event_level &value);
|
||||||
|
|
||||||
void set_event_level(const event_level &level) {
|
void set_encrypt_config(encrypt_config value);
|
||||||
if (set_value(event_level_, level)) {
|
|
||||||
event_system::instance().raise<event_level_changed>(
|
|
||||||
event_level_to_string(level));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_eviction_delay_mins(std::uint32_t eviction_delay_mins) {
|
void set_eviction_delay_mins(std::uint32_t value);
|
||||||
set_value(eviction_delay_mins_, eviction_delay_mins);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_eviction_uses_accessed_time(bool eviction_uses_accessed_time) {
|
void set_eviction_uses_accessed_time(bool value);
|
||||||
set_value(eviction_uses_accessed_time_, eviction_uses_accessed_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void set_high_frequency_interval_secs(std::uint16_t value);
|
||||||
set_high_frequency_interval_secs(std::uint8_t high_frequency_interval_secs) {
|
|
||||||
set_value(high_freq_interval_secs_, high_frequency_interval_secs);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(PROJECT_TESTING)
|
void set_host_config(host_config value);
|
||||||
void set_host_config(host_config hc) {
|
|
||||||
config_changed_ = true;
|
|
||||||
hc_ = std::move(hc);
|
|
||||||
save();
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_s3_config(s3_config s3) {
|
void set_low_frequency_interval_secs(std::uint16_t value);
|
||||||
config_changed_ = true;
|
|
||||||
s3_config_ = std::move(s3);
|
|
||||||
save();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void set_is_remote_mount(bool is_remote_mount);
|
void set_max_cache_size_bytes(std::uint64_t value);
|
||||||
|
|
||||||
void
|
void set_max_upload_count(std::uint8_t value);
|
||||||
set_low_frequency_interval_secs(std::uint32_t low_frequency_interval_secs) {
|
|
||||||
set_value(low_freq_interval_secs_, low_frequency_interval_secs);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_max_cache_size_bytes(std::uint64_t max_cache_size_bytes) {
|
void set_med_frequency_interval_secs(std::uint16_t value);
|
||||||
set_value(max_cache_size_bytes_, max_cache_size_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_max_upload_count(std::uint8_t max_upload_count) {
|
void set_online_check_retry_secs(std::uint16_t value);
|
||||||
set_value(max_upload_count_, max_upload_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_online_check_retry_secs(std::uint16_t online_check_retry_secs) {
|
void set_orphaned_file_retention_days(std::uint16_t value);
|
||||||
set_value(online_check_retry_secs_, online_check_retry_secs);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void set_preferred_download_type(const download_type &value);
|
||||||
set_orphaned_file_retention_days(std::uint16_t orphaned_file_retention_days) {
|
|
||||||
set_value(orphaned_file_retention_days_, orphaned_file_retention_days);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_preferred_download_type(const download_type &dt) {
|
void set_remote_config(remote::remote_config value);
|
||||||
set_value(preferred_download_type_, download_type_to_string(dt));
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_read_ahead_count(std::uint8_t read_ahead_count) {
|
void set_remote_mount(remote::remote_mount value);
|
||||||
set_value(read_ahead_count_, read_ahead_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_remote_client_pool_size(std::uint8_t remote_client_pool_size) {
|
void set_retry_read_count(std::uint16_t value);
|
||||||
set_value(remote_client_pool_size_, remote_client_pool_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_ring_buffer_file_size(std::uint16_t ring_buffer_file_size) {
|
void set_ring_buffer_file_size(std::uint16_t value);
|
||||||
set_value(ring_buffer_file_size_, ring_buffer_file_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_remote_host_name_or_ip(const std::string &remote_host_name_or_ip) {
|
void set_s3_config(s3_config value);
|
||||||
set_value(remote_host_name_or_ip_, remote_host_name_or_ip);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_remote_max_connections(std::uint8_t remote_max_connections) {
|
void set_sia_config(sia_config value);
|
||||||
set_value(remote_max_connections_, remote_max_connections);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_remote_port(std::uint16_t remote_port) {
|
void set_task_wait_ms(std::uint16_t value);
|
||||||
set_value(remote_port_, remote_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
set_remote_receive_timeout_secs(std::uint16_t remote_receive_timeout_secs) {
|
|
||||||
set_value(remote_receive_timeout_secs_, remote_receive_timeout_secs);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_remote_send_timeout_secs(std::uint16_t remote_send_timeout_secs) {
|
|
||||||
set_value(remote_send_timeout_secs_, remote_send_timeout_secs);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_remote_token(const std::string &remote_token) {
|
|
||||||
set_value(remote_token_, remote_token);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_retry_read_count(std::uint16_t retry_read_count) {
|
|
||||||
set_value(retry_read_count_, retry_read_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto set_value_by_name(const std::string &name,
|
[[nodiscard]] auto set_value_by_name(const std::string &name,
|
||||||
const std::string &value) -> std::string;
|
const std::string &value) -> std::string;
|
||||||
|
@ -39,8 +39,8 @@ struct http_put_file final : http_request_base {
|
|||||||
std::shared_ptr<utils::encryption::encrypting_reader> reader;
|
std::shared_ptr<utils::encryption::encrypting_reader> reader;
|
||||||
std::string source_path;
|
std::string source_path;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto set_method(CURL *curl, stop_type &stop_requested) const
|
||||||
set_method(CURL *curl, stop_type &stop_requested) const -> bool override;
|
-> bool override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable std::shared_ptr<read_file_info> read_info{};
|
mutable std::shared_ptr<read_file_info> read_info{};
|
||||||
|
@ -26,9 +26,7 @@
|
|||||||
#include "utils/file.hpp"
|
#include "utils/file.hpp"
|
||||||
|
|
||||||
namespace repertory::curl::requests {
|
namespace repertory::curl::requests {
|
||||||
using read_callback = size_t (*)(char *, size_t, size_t, void *);
|
using curl_response_callback =
|
||||||
|
|
||||||
using response_callback =
|
|
||||||
std::function<void(const data_buffer &data, long response_code)>;
|
std::function<void(const data_buffer &data, long response_code)>;
|
||||||
|
|
||||||
struct read_file_info final {
|
struct read_file_info final {
|
||||||
@ -37,19 +35,8 @@ struct read_file_info final {
|
|||||||
std::uint64_t offset{};
|
std::uint64_t offset{};
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const auto read_file_data = static_cast<read_callback>(
|
[[nodiscard]] auto curl_file_reader(char *buffer, size_t size, size_t nitems,
|
||||||
[](char *buffer, size_t size, size_t nitems, void *instream) -> size_t {
|
void *instream) -> size_t;
|
||||||
auto *read_info = reinterpret_cast<read_file_info *>(instream);
|
|
||||||
std::size_t bytes_read{};
|
|
||||||
auto ret =
|
|
||||||
read_info->file->read(reinterpret_cast<unsigned char *>(buffer),
|
|
||||||
size * nitems, read_info->offset, &bytes_read);
|
|
||||||
if (ret) {
|
|
||||||
read_info->offset += bytes_read;
|
|
||||||
}
|
|
||||||
return ret && not read_info->stop_requested ? bytes_read
|
|
||||||
: CURL_READFUNC_ABORT;
|
|
||||||
});
|
|
||||||
|
|
||||||
struct http_request_base {
|
struct http_request_base {
|
||||||
http_request_base() = default;
|
http_request_base() = default;
|
||||||
@ -68,14 +55,15 @@ struct http_request_base {
|
|||||||
std::string path{};
|
std::string path{};
|
||||||
http_query_parameters query{};
|
http_query_parameters query{};
|
||||||
std::optional<http_range> range{};
|
std::optional<http_range> range{};
|
||||||
std::optional<response_callback> response_handler;
|
std::optional<curl_response_callback> response_handler;
|
||||||
std::optional<http_headers> response_headers;
|
std::optional<http_headers> response_headers;
|
||||||
std::optional<std::uint64_t> total_size{};
|
std::optional<std::uint64_t> total_size{};
|
||||||
|
|
||||||
[[nodiscard]] virtual auto get_path() const -> std::string { return path; }
|
[[nodiscard]] virtual auto get_path() const -> std::string { return path; }
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto set_method(CURL *curl,
|
||||||
set_method(CURL *curl, stop_type &stop_requested) const -> bool = 0;
|
stop_type &stop_requested) const
|
||||||
|
-> bool = 0;
|
||||||
};
|
};
|
||||||
} // namespace repertory::curl::requests
|
} // namespace repertory::curl::requests
|
||||||
|
|
||||||
|
@ -52,23 +52,23 @@ public:
|
|||||||
~packet() = default;
|
~packet() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
data_buffer buffer_;
|
data_buffer buffer_{};
|
||||||
std::size_t decode_offset_ = 0U;
|
std::size_t decode_offset_{0U};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] static auto decode_json(packet &response,
|
[[nodiscard]] static auto decode_json(packet &response, json &json_data)
|
||||||
json &json_data) -> int;
|
-> int;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
[[nodiscard]] auto current_pointer() -> unsigned char * {
|
[[nodiscard]] auto current_pointer() -> unsigned char * {
|
||||||
return (decode_offset_ < buffer_.size()) ? &buffer_[decode_offset_]
|
return (decode_offset_ < buffer_.size()) ? &buffer_.at(decode_offset_)
|
||||||
: nullptr;
|
: nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto current_pointer() const -> const unsigned char * {
|
[[nodiscard]] auto current_pointer() const -> const unsigned char * {
|
||||||
return (decode_offset_ < buffer_.size()) ? &buffer_[decode_offset_]
|
return (decode_offset_ < buffer_.size()) ? &buffer_.at(decode_offset_)
|
||||||
: nullptr;
|
: nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,7 +206,7 @@ public:
|
|||||||
return static_cast<std::uint32_t>(buffer_.size());
|
return static_cast<std::uint32_t>(buffer_.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void transfer_into(data_buffer &buffer);
|
void to_buffer(data_buffer &buffer);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
auto operator=(const data_buffer &buffer) noexcept -> packet &;
|
auto operator=(const data_buffer &buffer) noexcept -> packet &;
|
||||||
@ -226,8 +226,6 @@ public:
|
|||||||
return buffer_.at(index);
|
return buffer_.at(index);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using packet = packet;
|
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
|
||||||
#endif // REPERTORY_INCLUDE_COMM_PACKET_PACKET_HPP_
|
#endif // REPERTORY_INCLUDE_COMM_PACKET_PACKET_HPP_
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#define REPERTORY_INCLUDE_COMM_PACKET_PACKET_CLIENT_HPP_
|
#define REPERTORY_INCLUDE_COMM_PACKET_PACKET_CLIENT_HPP_
|
||||||
|
|
||||||
#include "comm/packet/packet.hpp"
|
#include "comm/packet/packet.hpp"
|
||||||
|
#include "types/remote.hpp"
|
||||||
|
|
||||||
using boost::asio::ip::tcp;
|
using boost::asio::ip::tcp;
|
||||||
|
|
||||||
@ -36,9 +37,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
packet_client(std::string host_name_or_ip, std::uint8_t max_connections,
|
packet_client(remote::remote_config cfg);
|
||||||
std::uint16_t port, std::uint16_t receive_timeout,
|
|
||||||
std::uint16_t send_timeout, std::string encryption_token);
|
|
||||||
|
|
||||||
~packet_client();
|
~packet_client();
|
||||||
|
|
||||||
@ -49,12 +48,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
boost::asio::io_context io_context_;
|
boost::asio::io_context io_context_;
|
||||||
std::string host_name_or_ip_;
|
remote::remote_config cfg_;
|
||||||
std::uint8_t max_connections_;
|
|
||||||
std::uint16_t port_;
|
|
||||||
std::uint16_t receive_timeout_;
|
|
||||||
std::uint16_t send_timeout_;
|
|
||||||
std::string encryption_token_;
|
|
||||||
std::string unique_id_;
|
std::string unique_id_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -75,21 +69,21 @@ private:
|
|||||||
|
|
||||||
void put_client(std::shared_ptr<client> &cli);
|
void put_client(std::shared_ptr<client> &cli);
|
||||||
|
|
||||||
[[nodiscard]] auto read_packet(client &cli,
|
[[nodiscard]] auto read_packet(client &cli, packet &response)
|
||||||
packet &response) -> packet::error_type;
|
-> packet::error_type;
|
||||||
|
|
||||||
void resolve();
|
void resolve();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] auto send(std::string_view method,
|
[[nodiscard]] auto send(std::string_view method, std::uint32_t &service_flags)
|
||||||
std::uint32_t &service_flags) -> packet::error_type;
|
-> packet::error_type;
|
||||||
|
|
||||||
[[nodiscard]] auto send(std::string_view method, packet &request,
|
[[nodiscard]] auto send(std::string_view method, packet &request,
|
||||||
std::uint32_t &service_flags) -> packet::error_type;
|
std::uint32_t &service_flags) -> packet::error_type;
|
||||||
|
|
||||||
[[nodiscard]] auto send(std::string_view method, packet &request,
|
[[nodiscard]] auto send(std::string_view method, packet &request,
|
||||||
packet &response,
|
packet &response, std::uint32_t &service_flags)
|
||||||
std::uint32_t &service_flags) -> packet::error_type;
|
-> packet::error_type;
|
||||||
};
|
};
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
|
||||||
|
@ -52,8 +52,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
struct connection {
|
struct connection {
|
||||||
connection(boost::asio::io_service &io_service, tcp::acceptor &acceptor_)
|
connection(io_context &ctx, tcp::acceptor &acceptor_)
|
||||||
: socket(io_service), acceptor(acceptor_) {}
|
: socket(ctx), acceptor(acceptor_) {}
|
||||||
|
|
||||||
tcp::socket socket;
|
tcp::socket socket;
|
||||||
tcp::acceptor &acceptor;
|
tcp::acceptor &acceptor;
|
||||||
@ -68,7 +68,7 @@ private:
|
|||||||
std::string encryption_token_;
|
std::string encryption_token_;
|
||||||
closed_callback closed_;
|
closed_callback closed_;
|
||||||
message_handler_callback message_handler_;
|
message_handler_callback message_handler_;
|
||||||
boost::asio::io_context io_context_;
|
io_context io_context_;
|
||||||
std::unique_ptr<std::thread> server_thread_;
|
std::unique_ptr<std::thread> server_thread_;
|
||||||
std::vector<std::thread> service_threads_;
|
std::vector<std::thread> service_threads_;
|
||||||
std::recursive_mutex connection_mutex_;
|
std::recursive_mutex connection_mutex_;
|
||||||
|
34
repertory/librepertory/include/db/file_db.hpp
Normal file
34
repertory/librepertory/include/db/file_db.hpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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_DB_FILE_DB_HPP_
|
||||||
|
#define REPERTORY_INCLUDE_DB_FILE_DB_HPP_
|
||||||
|
|
||||||
|
#include "db/i_file_db.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
class app_config;
|
||||||
|
|
||||||
|
[[nodiscard]] auto create_file_db(const app_config &cfg)
|
||||||
|
-> std::unique_ptr<i_file_db>;
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
|
#endif // REPERTORY_INCLUDE_DB_FILE_DB_HPP_
|
34
repertory/librepertory/include/db/file_mgr_db.hpp
Normal file
34
repertory/librepertory/include/db/file_mgr_db.hpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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_DB_FILE_MGR_DB_HPP_
|
||||||
|
#define REPERTORY_INCLUDE_DB_FILE_MGR_DB_HPP_
|
||||||
|
|
||||||
|
#include "db/i_file_mgr_db.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
class app_config;
|
||||||
|
|
||||||
|
[[nodiscard]] auto
|
||||||
|
create_file_mgr_db(const app_config &cfg) -> std::unique_ptr<i_file_mgr_db>;
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
|
#endif // REPERTORY_INCLUDE_DB_FILE_MGR_DB_HPP_
|
95
repertory/librepertory/include/db/i_file_db.hpp
Normal file
95
repertory/librepertory/include/db/i_file_db.hpp
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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_DB_I_FILE_DB_HPP_
|
||||||
|
#define REPERTORY_INCLUDE_DB_I_FILE_DB_HPP_
|
||||||
|
|
||||||
|
#include "types/repertory.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
class i_file_db {
|
||||||
|
INTERFACE_SETUP(i_file_db);
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct file_info final {
|
||||||
|
std::string api_path;
|
||||||
|
bool directory;
|
||||||
|
std::string source_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct file_data final {
|
||||||
|
std::string api_path;
|
||||||
|
std::uint64_t file_size{};
|
||||||
|
std::vector<
|
||||||
|
std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>
|
||||||
|
iv_list{};
|
||||||
|
std::string source_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
[[nodiscard]] virtual auto add_directory(const std::string &api_path,
|
||||||
|
const std::string &source_path)
|
||||||
|
-> api_error = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto add_or_update_file(const file_data &data)
|
||||||
|
-> api_error = 0;
|
||||||
|
|
||||||
|
virtual void clear() = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto count() const -> std::uint64_t = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_api_path(const std::string &source_path,
|
||||||
|
std::string &api_path) const
|
||||||
|
-> api_error = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto
|
||||||
|
get_directory_api_path(const std::string &source_path,
|
||||||
|
std::string &api_path) const -> api_error = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto
|
||||||
|
get_directory_source_path(const std::string &api_path,
|
||||||
|
std::string &source_path) const -> api_error = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_file_api_path(const std::string &source_path,
|
||||||
|
std::string &api_path) const
|
||||||
|
-> api_error = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_file_data(const std::string &api_path,
|
||||||
|
file_data &data) const
|
||||||
|
-> api_error = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto
|
||||||
|
get_file_source_path(const std::string &api_path,
|
||||||
|
std::string &source_path) const -> api_error = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_item_list() const
|
||||||
|
-> std::vector<file_info> = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_source_path(const std::string &api_path,
|
||||||
|
std::string &source_path) const
|
||||||
|
-> api_error = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto remove_item(const std::string &api_path)
|
||||||
|
-> api_error = 0;
|
||||||
|
};
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
|
#endif // REPERTORY_INCLUDE_DB_I_FILE_DB_HPP_
|
86
repertory/librepertory/include/db/i_file_mgr_db.hpp
Normal file
86
repertory/librepertory/include/db/i_file_mgr_db.hpp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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_DB_I_FILE_MGR_DB_HPP_
|
||||||
|
#define REPERTORY_INCLUDE_DB_I_FILE_MGR_DB_HPP_
|
||||||
|
|
||||||
|
#include "types/repertory.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
class i_file_mgr_db {
|
||||||
|
INTERFACE_SETUP(i_file_mgr_db);
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct resume_entry final {
|
||||||
|
std::string api_path;
|
||||||
|
std::uint64_t chunk_size{};
|
||||||
|
boost::dynamic_bitset<> read_state;
|
||||||
|
std::string source_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct upload_active_entry final {
|
||||||
|
std::string api_path;
|
||||||
|
std::string source_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct upload_entry final {
|
||||||
|
std::string api_path;
|
||||||
|
std::string source_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
[[nodiscard]] virtual auto add_resume(const resume_entry &entry) -> bool = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto add_upload(const upload_entry &entry) -> bool = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto add_upload_active(const upload_active_entry &entry)
|
||||||
|
-> bool = 0;
|
||||||
|
|
||||||
|
virtual void clear() = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_next_upload() const
|
||||||
|
-> std::optional<upload_entry> = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_resume_list() const
|
||||||
|
-> std::vector<resume_entry> = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_upload(const std::string &api_path) const
|
||||||
|
-> std::optional<upload_entry> = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_upload_active_list() const
|
||||||
|
-> std::vector<upload_active_entry> = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto remove_resume(const std::string &api_path)
|
||||||
|
-> bool = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto remove_upload(const std::string &api_path)
|
||||||
|
-> bool = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto remove_upload_active(const std::string &api_path)
|
||||||
|
-> bool = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto rename_resume(const std::string &from_api_path,
|
||||||
|
const std::string &to_api_path)
|
||||||
|
-> bool = 0;
|
||||||
|
};
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
|
#endif // REPERTORY_INCLUDE_DB_I_FILE_MGR_DB_HPP_
|
78
repertory/librepertory/include/db/i_meta_db.hpp
Normal file
78
repertory/librepertory/include/db/i_meta_db.hpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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_DB_I_META_DB_HPP_
|
||||||
|
#define REPERTORY_INCLUDE_DB_I_META_DB_HPP_
|
||||||
|
|
||||||
|
#include "types/repertory.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
class i_meta_db {
|
||||||
|
INTERFACE_SETUP(i_meta_db);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual void clear() = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_api_path(const std::string &source_path,
|
||||||
|
std::string &api_path) const
|
||||||
|
-> api_error = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_api_path_list() const
|
||||||
|
-> std::vector<std::string> = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_item_meta(const std::string &api_path,
|
||||||
|
api_meta_map &meta) const
|
||||||
|
-> api_error = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_item_meta(const std::string &api_path,
|
||||||
|
const std::string &key,
|
||||||
|
std::string &value) const
|
||||||
|
-> api_error = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_pinned_files() const
|
||||||
|
-> std::vector<std::string> = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_total_item_count() const -> std::uint64_t = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_total_size() const -> std::uint64_t = 0;
|
||||||
|
|
||||||
|
virtual void remove_api_path(const std::string &api_path) = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto remove_item_meta(const std::string &api_path,
|
||||||
|
const std::string &key)
|
||||||
|
-> api_error = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto rename_item_meta(const std::string &from_api_path,
|
||||||
|
const std::string &to_api_path)
|
||||||
|
-> api_error = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto set_item_meta(const std::string &api_path,
|
||||||
|
const std::string &key,
|
||||||
|
const std::string &value)
|
||||||
|
-> api_error = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto set_item_meta(const std::string &api_path,
|
||||||
|
const api_meta_map &meta)
|
||||||
|
-> api_error = 0;
|
||||||
|
};
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
|
#endif // REPERTORY_INCLUDE_DB_I_META_DB_HPP_
|
117
repertory/librepertory/include/db/impl/rdb_file_db.hpp
Normal file
117
repertory/librepertory/include/db/impl/rdb_file_db.hpp
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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_DB_IMPL_RDB_FILE_DB_HPP_
|
||||||
|
#define REPERTORY_INCLUDE_DB_IMPL_RDB_FILE_DB_HPP_
|
||||||
|
|
||||||
|
#include "db/i_file_db.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
class app_config;
|
||||||
|
|
||||||
|
class rdb_file_db final : public i_file_db {
|
||||||
|
public:
|
||||||
|
rdb_file_db(const app_config &cfg);
|
||||||
|
~rdb_file_db() override;
|
||||||
|
|
||||||
|
rdb_file_db(const rdb_file_db &) = delete;
|
||||||
|
rdb_file_db(rdb_file_db &&) = delete;
|
||||||
|
auto operator=(const rdb_file_db &) -> rdb_file_db & = delete;
|
||||||
|
auto operator=(rdb_file_db &&) -> rdb_file_db & = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const app_config &cfg_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<rocksdb::TransactionDB> db_{nullptr};
|
||||||
|
rocksdb::ColumnFamilyHandle *directory_family_{};
|
||||||
|
rocksdb::ColumnFamilyHandle *file_family_{};
|
||||||
|
rocksdb::ColumnFamilyHandle *path_family_{};
|
||||||
|
rocksdb::ColumnFamilyHandle *source_family_{};
|
||||||
|
|
||||||
|
private:
|
||||||
|
void create_or_open(bool clear);
|
||||||
|
|
||||||
|
[[nodiscard]] auto create_iterator(rocksdb::ColumnFamilyHandle *family) const
|
||||||
|
-> std::shared_ptr<rocksdb::Iterator>;
|
||||||
|
|
||||||
|
[[nodiscard]] static auto
|
||||||
|
perform_action(std::string_view function_name,
|
||||||
|
std::function<rocksdb::Status()> action) -> api_error;
|
||||||
|
|
||||||
|
[[nodiscard]] auto perform_action(
|
||||||
|
std::string_view function_name,
|
||||||
|
std::function<rocksdb::Status(rocksdb::Transaction *txn)> action)
|
||||||
|
-> api_error;
|
||||||
|
|
||||||
|
[[nodiscard]] auto remove_item(const std::string &api_path,
|
||||||
|
const std::string &source_path,
|
||||||
|
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_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;
|
||||||
|
|
||||||
|
[[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_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_item_list() const -> std::vector<i_file_db::file_info> 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;
|
||||||
|
};
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
|
#endif // REPERTORY_INCLUDE_DB_IMPL_RDB_FILE_DB_HPP_
|
109
repertory/librepertory/include/db/impl/rdb_file_mgr_db.hpp
Normal file
109
repertory/librepertory/include/db/impl/rdb_file_mgr_db.hpp
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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_DB_IMPL_RDB_FILE_MGR_DB_HPP_
|
||||||
|
#define REPERTORY_INCLUDE_DB_IMPL_RDB_FILE_MGR_DB_HPP_
|
||||||
|
|
||||||
|
#include "db/i_file_mgr_db.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
class app_config;
|
||||||
|
|
||||||
|
class rdb_file_mgr_db final : public i_file_mgr_db {
|
||||||
|
public:
|
||||||
|
rdb_file_mgr_db(const app_config &cfg);
|
||||||
|
~rdb_file_mgr_db() override;
|
||||||
|
|
||||||
|
rdb_file_mgr_db(const rdb_file_mgr_db &) = delete;
|
||||||
|
rdb_file_mgr_db(rdb_file_mgr_db &&) = delete;
|
||||||
|
auto operator=(const rdb_file_mgr_db &) -> rdb_file_mgr_db & = delete;
|
||||||
|
auto operator=(rdb_file_mgr_db &&) -> rdb_file_mgr_db & = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const app_config &cfg_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<rocksdb::TransactionDB> db_{nullptr};
|
||||||
|
std::atomic<std::uint64_t> id_{0U};
|
||||||
|
rocksdb::ColumnFamilyHandle *resume_family_{};
|
||||||
|
rocksdb::ColumnFamilyHandle *upload_active_family_{};
|
||||||
|
rocksdb::ColumnFamilyHandle *upload_family_{};
|
||||||
|
|
||||||
|
private:
|
||||||
|
void create_or_open(bool clear);
|
||||||
|
|
||||||
|
[[nodiscard]] auto create_iterator(rocksdb::ColumnFamilyHandle *family) const
|
||||||
|
-> std::shared_ptr<rocksdb::Iterator>;
|
||||||
|
|
||||||
|
[[nodiscard]] static auto
|
||||||
|
perform_action(std::string_view function_name,
|
||||||
|
std::function<rocksdb::Status()> action) -> bool;
|
||||||
|
|
||||||
|
[[nodiscard]] auto perform_action(
|
||||||
|
std::string_view function_name,
|
||||||
|
std::function<rocksdb::Status(rocksdb::Transaction *txn)> action) -> bool;
|
||||||
|
|
||||||
|
[[nodiscard]] auto remove_resume(const std::string &api_path,
|
||||||
|
rocksdb::Transaction *txn)
|
||||||
|
-> rocksdb::Status;
|
||||||
|
|
||||||
|
[[nodiscard]] auto add_resume(const resume_entry &entry,
|
||||||
|
rocksdb::Transaction *txn) -> rocksdb::Status;
|
||||||
|
|
||||||
|
public:
|
||||||
|
[[nodiscard]] auto add_resume(const resume_entry &entry) -> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto add_upload(const upload_entry &entry) -> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto add_upload_active(const upload_active_entry &entry)
|
||||||
|
-> bool override;
|
||||||
|
|
||||||
|
void clear() override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_next_upload() const
|
||||||
|
-> std::optional<upload_entry> override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_resume_list() const
|
||||||
|
-> std::vector<resume_entry> override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_upload(const std::string &api_path) const
|
||||||
|
-> std::optional<upload_entry> override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_upload_active_list() const
|
||||||
|
-> std::vector<upload_active_entry> override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto remove_resume(const std::string &api_path)
|
||||||
|
-> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto remove_upload(const std::string &api_path)
|
||||||
|
-> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto remove_upload_active(const std::string &api_path)
|
||||||
|
-> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto rename_resume(const std::string &from_api_path,
|
||||||
|
const std::string &to_api_path)
|
||||||
|
-> bool override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
|
#endif // REPERTORY_INCLUDE_DB_IMPL_RDB_FILE_MGR_DB_HPP_
|
127
repertory/librepertory/include/db/impl/rdb_meta_db.hpp
Normal file
127
repertory/librepertory/include/db/impl/rdb_meta_db.hpp
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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_DB_IMPL_RDB_META_DB_HPP_
|
||||||
|
#define REPERTORY_INCLUDE_DB_IMPL_RDB_META_DB_HPP_
|
||||||
|
|
||||||
|
#include "db/i_meta_db.hpp"
|
||||||
|
#include "types/repertory.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
class app_config;
|
||||||
|
|
||||||
|
class rdb_meta_db final : public i_meta_db {
|
||||||
|
public:
|
||||||
|
rdb_meta_db(const app_config &cfg);
|
||||||
|
~rdb_meta_db() override;
|
||||||
|
|
||||||
|
rdb_meta_db(const rdb_meta_db &) = delete;
|
||||||
|
rdb_meta_db(rdb_meta_db &&) = delete;
|
||||||
|
auto operator=(const rdb_meta_db &) -> rdb_meta_db & = delete;
|
||||||
|
auto operator=(rdb_meta_db &&) -> rdb_meta_db & = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const app_config &cfg_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<rocksdb::TransactionDB> db_{nullptr};
|
||||||
|
rocksdb::ColumnFamilyHandle *meta_family_{};
|
||||||
|
rocksdb::ColumnFamilyHandle *pinned_family_{};
|
||||||
|
rocksdb::ColumnFamilyHandle *size_family_{};
|
||||||
|
rocksdb::ColumnFamilyHandle *source_family_{};
|
||||||
|
|
||||||
|
private:
|
||||||
|
[[nodiscard]] auto create_iterator(rocksdb::ColumnFamilyHandle *family) const
|
||||||
|
-> std::shared_ptr<rocksdb::Iterator>;
|
||||||
|
|
||||||
|
void create_or_open(bool clear);
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_item_meta_json(const std::string &api_path,
|
||||||
|
json &json_data) const -> api_error;
|
||||||
|
|
||||||
|
[[nodiscard]] static auto
|
||||||
|
perform_action(std::string_view function_name,
|
||||||
|
std::function<rocksdb::Status()> action) -> api_error;
|
||||||
|
|
||||||
|
[[nodiscard]] auto perform_action(
|
||||||
|
std::string_view function_name,
|
||||||
|
std::function<rocksdb::Status(rocksdb::Transaction *txn)> action)
|
||||||
|
-> api_error;
|
||||||
|
|
||||||
|
[[nodiscard]] auto remove_api_path(const std::string &api_path,
|
||||||
|
const std::string &source_path,
|
||||||
|
rocksdb::Transaction *txn)
|
||||||
|
-> rocksdb::Status;
|
||||||
|
|
||||||
|
[[nodiscard]] auto update_item_meta(const std::string &api_path,
|
||||||
|
json json_data,
|
||||||
|
rocksdb::Transaction *base_txn = nullptr,
|
||||||
|
rocksdb::Status *status = nullptr)
|
||||||
|
-> api_error;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void clear() override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_api_path(const std::string &source_path,
|
||||||
|
std::string &api_path) const
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_api_path_list() const
|
||||||
|
-> std::vector<std::string> override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_item_meta(const std::string &api_path,
|
||||||
|
api_meta_map &meta) const
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_item_meta(const std::string &api_path,
|
||||||
|
const std::string &key,
|
||||||
|
std::string &value) const
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_pinned_files() const
|
||||||
|
-> std::vector<std::string> override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_total_item_count() const -> std::uint64_t override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_total_size() const -> std::uint64_t override;
|
||||||
|
|
||||||
|
void remove_api_path(const std::string &api_path) override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto remove_item_meta(const std::string &api_path,
|
||||||
|
const std::string &key)
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto rename_item_meta(const std::string &from_api_path,
|
||||||
|
const std::string &to_api_path)
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto set_item_meta(const std::string &api_path,
|
||||||
|
const std::string &key,
|
||||||
|
const std::string &value)
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto set_item_meta(const std::string &api_path,
|
||||||
|
const api_meta_map &meta)
|
||||||
|
-> api_error override;
|
||||||
|
};
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
|
#endif // REPERTORY_INCLUDE_DB_IMPL_RDB_META_DB_HPP_
|
92
repertory/librepertory/include/db/impl/sqlite_file_db.hpp
Normal file
92
repertory/librepertory/include/db/impl/sqlite_file_db.hpp
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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_DB_IMPL_SQLITE_FILE_DB_HPP_
|
||||||
|
#define REPERTORY_INCLUDE_DB_IMPL_SQLITE_FILE_DB_HPP_
|
||||||
|
|
||||||
|
#include "db/i_file_db.hpp"
|
||||||
|
#include "utils/db/sqlite/db_common.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
class app_config;
|
||||||
|
|
||||||
|
class sqlite_file_db final : public i_file_db {
|
||||||
|
public:
|
||||||
|
sqlite_file_db(const app_config &cfg);
|
||||||
|
~sqlite_file_db() override;
|
||||||
|
|
||||||
|
sqlite_file_db(const sqlite_file_db &) = delete;
|
||||||
|
sqlite_file_db(sqlite_file_db &&) = delete;
|
||||||
|
auto operator=(const sqlite_file_db &) -> sqlite_file_db & = delete;
|
||||||
|
auto operator=(sqlite_file_db &&) -> sqlite_file_db & = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
utils::db::sqlite::db3_t db_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
[[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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
[[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_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_item_list() const
|
||||||
|
-> std::vector<i_file_db::file_info> 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;
|
||||||
|
};
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
|
#endif // REPERTORY_INCLUDE_DB_IMPL_SQLITE_FILE_DB_HPP_
|
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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_DB_IMPL_SQLITE_FILE_MGR_DB_HPP_
|
||||||
|
#define REPERTORY_INCLUDE_DB_IMPL_SQLITE_FILE_MGR_DB_HPP_
|
||||||
|
|
||||||
|
#include "db/i_file_mgr_db.hpp"
|
||||||
|
#include "utils/db/sqlite/db_common.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
class app_config;
|
||||||
|
|
||||||
|
class sqlite_file_mgr_db final : public i_file_mgr_db {
|
||||||
|
public:
|
||||||
|
sqlite_file_mgr_db(const app_config &cfg);
|
||||||
|
~sqlite_file_mgr_db() override;
|
||||||
|
|
||||||
|
sqlite_file_mgr_db(const sqlite_file_mgr_db &) = delete;
|
||||||
|
sqlite_file_mgr_db(sqlite_file_mgr_db &&) = delete;
|
||||||
|
auto operator=(const sqlite_file_mgr_db &) -> sqlite_file_mgr_db & = delete;
|
||||||
|
auto operator=(sqlite_file_mgr_db &&) -> sqlite_file_mgr_db & = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
utils::db::sqlite::db3_t db_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
[[nodiscard]] auto add_resume(const resume_entry &entry) -> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto add_upload(const upload_entry &entry) -> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto add_upload_active(const upload_active_entry &entry)
|
||||||
|
-> bool override;
|
||||||
|
|
||||||
|
void clear() override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_next_upload() const
|
||||||
|
-> std::optional<upload_entry> override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_resume_list() const
|
||||||
|
-> std::vector<resume_entry> override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_upload(const std::string &api_path) const
|
||||||
|
-> std::optional<upload_entry> override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_upload_active_list() const
|
||||||
|
-> std::vector<upload_active_entry> override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto remove_resume(const std::string &api_path)
|
||||||
|
-> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto remove_upload(const std::string &api_path)
|
||||||
|
-> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto remove_upload_active(const std::string &api_path)
|
||||||
|
-> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto rename_resume(const std::string &from_api_path,
|
||||||
|
const std::string &to_api_path)
|
||||||
|
-> bool override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
|
#endif // REPERTORY_INCLUDE_DB_IMPL_SQLITE_FILE_MGR_DB_HPP_
|
@ -19,24 +19,25 @@
|
|||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#ifndef REPERTORY_INCLUDE_PROVIDERS_META_DB_HPP_
|
#ifndef REPERTORY_INCLUDE_DB_IMPL_SQLITE_META_DB_HPP_
|
||||||
#define REPERTORY_INCLUDE_PROVIDERS_META_DB_HPP_
|
#define REPERTORY_INCLUDE_DB_IMPL_SQLITE_META_DB_HPP_
|
||||||
|
|
||||||
|
#include "db/i_meta_db.hpp"
|
||||||
#include "types/repertory.hpp"
|
#include "types/repertory.hpp"
|
||||||
#include "utils/db/sqlite/db_common.hpp"
|
#include "utils/db/sqlite/db_common.hpp"
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
class app_config;
|
class app_config;
|
||||||
|
|
||||||
class meta_db final {
|
class sqlite_meta_db final : public i_meta_db {
|
||||||
public:
|
public:
|
||||||
meta_db(const app_config &cfg);
|
sqlite_meta_db(const app_config &cfg);
|
||||||
~meta_db();
|
~sqlite_meta_db() override;
|
||||||
|
|
||||||
meta_db(const meta_db &) = delete;
|
sqlite_meta_db(const sqlite_meta_db &) = delete;
|
||||||
meta_db(meta_db &&) = delete;
|
sqlite_meta_db(sqlite_meta_db &&) = delete;
|
||||||
auto operator=(const meta_db &) -> meta_db & = delete;
|
auto operator=(const sqlite_meta_db &) -> sqlite_meta_db & = delete;
|
||||||
auto operator=(meta_db &&) -> meta_db & = delete;
|
auto operator=(sqlite_meta_db &&) -> sqlite_meta_db & = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
utils::db::sqlite::db3_t db_;
|
utils::db::sqlite::db3_t db_;
|
||||||
@ -47,38 +48,50 @@ private:
|
|||||||
api_meta_map meta) -> api_error;
|
api_meta_map meta) -> api_error;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] auto get_api_path(const std::string &source_path,
|
void clear() override;
|
||||||
std::string &api_path) -> api_error;
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_api_path_list() -> std::vector<std::string>;
|
[[nodiscard]] auto get_api_path(const std::string &source_path,
|
||||||
|
std::string &api_path) const
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_api_path_list() const
|
||||||
|
-> std::vector<std::string> override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_item_meta(const std::string &api_path,
|
[[nodiscard]] auto get_item_meta(const std::string &api_path,
|
||||||
api_meta_map &meta) -> api_error;
|
api_meta_map &meta) const
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_item_meta(const std::string &api_path,
|
[[nodiscard]] auto get_item_meta(const std::string &api_path,
|
||||||
const std::string &key,
|
const std::string &key,
|
||||||
std::string &value) const -> api_error;
|
std::string &value) const
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_pinned_files() const -> std::vector<std::string>;
|
[[nodiscard]] auto get_pinned_files() const
|
||||||
|
-> std::vector<std::string> override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_total_item_count() const -> std::uint64_t;
|
[[nodiscard]] auto get_total_item_count() const -> std::uint64_t override;
|
||||||
|
|
||||||
void remove_api_path(const std::string &api_path);
|
[[nodiscard]] auto get_total_size() const -> std::uint64_t override;
|
||||||
|
|
||||||
|
void remove_api_path(const std::string &api_path) override;
|
||||||
|
|
||||||
[[nodiscard]] auto remove_item_meta(const std::string &api_path,
|
[[nodiscard]] auto remove_item_meta(const std::string &api_path,
|
||||||
const std::string &key) -> api_error;
|
const std::string &key)
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto rename_item_meta(const std::string &from_api_path,
|
||||||
rename_item_meta(const std::string &from_api_path,
|
const std::string &to_api_path)
|
||||||
const std::string &to_api_path) -> api_error;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto set_item_meta(const std::string &api_path,
|
[[nodiscard]] auto set_item_meta(const std::string &api_path,
|
||||||
const std::string &key,
|
const std::string &key,
|
||||||
const std::string &value) -> api_error;
|
const std::string &value)
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto set_item_meta(const std::string &api_path,
|
[[nodiscard]] auto set_item_meta(const std::string &api_path,
|
||||||
const api_meta_map &meta) -> api_error;
|
const api_meta_map &meta)
|
||||||
|
-> api_error override;
|
||||||
};
|
};
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
|
||||||
#endif // REPERTORY_INCLUDE_PROVIDERS_META_DB_HPP_
|
#endif // REPERTORY_INCLUDE_DB_IMPL_SQLITE_META_DB_HPP_
|
34
repertory/librepertory/include/db/meta_db.hpp
Normal file
34
repertory/librepertory/include/db/meta_db.hpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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_DB_META_DB_HPP_
|
||||||
|
#define REPERTORY_INCLUDE_DB_META_DB_HPP_
|
||||||
|
|
||||||
|
#include "db/i_meta_db.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
class app_config;
|
||||||
|
|
||||||
|
[[nodiscard]] auto create_meta_db(const app_config &cfg)
|
||||||
|
-> std::unique_ptr<i_meta_db>;
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
|
#endif // REPERTORY_INCLUDE_DB_META_DB_HPP_
|
@ -34,7 +34,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
struct open_directory final {
|
struct open_directory final {
|
||||||
std::shared_ptr<directory_iterator> iterator;
|
std::shared_ptr<directory_iterator> iterator;
|
||||||
std::vector<std::uint64_t> handles{};
|
std::vector<std::uint64_t> handles;
|
||||||
std::chrono::system_clock::time_point last_update{
|
std::chrono::system_clock::time_point last_update{
|
||||||
std::chrono::system_clock::now()};
|
std::chrono::system_clock::now()};
|
||||||
};
|
};
|
||||||
@ -60,8 +60,8 @@ public:
|
|||||||
void execute_action(const std::string &api_path,
|
void execute_action(const std::string &api_path,
|
||||||
const execute_callback &execute);
|
const execute_callback &execute);
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto get_directory(std::uint64_t handle)
|
||||||
get_directory(std::uint64_t handle) -> std::shared_ptr<directory_iterator>;
|
-> std::shared_ptr<directory_iterator>;
|
||||||
|
|
||||||
[[nodiscard]] auto remove_directory(const std::string &api_path)
|
[[nodiscard]] auto remove_directory(const std::string &api_path)
|
||||||
-> std::shared_ptr<directory_iterator>;
|
-> std::shared_ptr<directory_iterator>;
|
||||||
|
@ -31,22 +31,23 @@ class i_provider;
|
|||||||
|
|
||||||
class eviction final : public single_thread_service_base {
|
class eviction final : public single_thread_service_base {
|
||||||
public:
|
public:
|
||||||
eviction(i_provider &provider, const app_config &config, i_file_manager &fm)
|
eviction(i_provider &provider, const app_config &config,
|
||||||
|
i_file_manager &file_mgr)
|
||||||
: single_thread_service_base("eviction"),
|
: single_thread_service_base("eviction"),
|
||||||
provider_(provider),
|
|
||||||
config_(config),
|
config_(config),
|
||||||
fm_(fm) {}
|
file_mgr_(file_mgr),
|
||||||
|
provider_(provider) {}
|
||||||
|
|
||||||
~eviction() override = default;
|
~eviction() override = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
i_provider &provider_;
|
|
||||||
const app_config &config_;
|
const app_config &config_;
|
||||||
i_file_manager &fm_;
|
i_file_manager &file_mgr_;
|
||||||
|
i_provider &provider_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto check_minimum_requirements(const std::string &file_path)
|
||||||
check_minimum_requirements(const std::string &file_path) -> bool;
|
-> bool;
|
||||||
|
|
||||||
[[nodiscard]] auto get_filtered_cached_files() -> std::deque<std::string>;
|
[[nodiscard]] auto get_filtered_cached_files() -> std::deque<std::string>;
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ protected:
|
|||||||
struct fuse_file_info *file_info) -> api_error override;
|
struct fuse_file_info *file_info) -> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto
|
||||||
fgetattr_impl(std::string api_path, struct stat *st,
|
fgetattr_impl(std::string api_path, struct stat *unix_st,
|
||||||
struct fuse_file_info *file_info) -> api_error override;
|
struct fuse_file_info *file_info) -> api_error override;
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
@ -124,11 +124,11 @@ protected:
|
|||||||
|
|
||||||
#if FUSE_USE_VERSION >= 30
|
#if FUSE_USE_VERSION >= 30
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto
|
||||||
getattr_impl(std::string api_path, struct stat *st,
|
getattr_impl(std::string api_path, struct stat *unix_st,
|
||||||
struct fuse_file_info *file_info) -> api_error override;
|
struct fuse_file_info *file_info) -> api_error override;
|
||||||
#else
|
#else
|
||||||
[[nodiscard]] auto getattr_impl(std::string api_path,
|
[[nodiscard]] auto getattr_impl(std::string api_path,
|
||||||
struct stat *st) -> api_error override;
|
struct stat *unix_st) -> api_error override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
|
@ -49,9 +49,9 @@ private:
|
|||||||
|
|
||||||
[[nodiscard]] auto get_next_handle() -> std::uint64_t;
|
[[nodiscard]] auto get_next_handle() -> std::uint64_t;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto populate_file_info(const std::string &api_path,
|
||||||
populate_file_info(const std::string &api_path,
|
remote::file_info &file_info)
|
||||||
remote::file_info &file_info) -> packet::error_type;
|
-> packet::error_type;
|
||||||
|
|
||||||
void populate_file_info(const std::string &api_path, const UINT64 &file_size,
|
void populate_file_info(const std::string &api_path, const UINT64 &file_size,
|
||||||
const UINT32 &attributes,
|
const UINT32 &attributes,
|
||||||
@ -72,14 +72,14 @@ public:
|
|||||||
[[nodiscard]] auto fuse_chmod(const char *path, const remote::file_mode &mode)
|
[[nodiscard]] auto fuse_chmod(const char *path, const remote::file_mode &mode)
|
||||||
-> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto fuse_chown(const char *path, const remote::user_id &uid,
|
||||||
fuse_chown(const char *path, const remote::user_id &uid,
|
const remote::group_id &gid)
|
||||||
const remote::group_id &gid) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto
|
||||||
fuse_create(const char *path, const remote::file_mode &mode,
|
fuse_create(const char *path, const remote::file_mode &mode,
|
||||||
const remote::open_flags &flags,
|
const remote::open_flags &flags, remote::file_handle &handle)
|
||||||
remote::file_handle &handle) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto fuse_destroy() -> packet::error_type override;
|
[[nodiscard]] auto fuse_destroy() -> packet::error_type override;
|
||||||
|
|
||||||
@ -88,25 +88,28 @@ public:
|
|||||||
remote::file_offset &length, const remote::file_handle &handle) override
|
remote::file_offset &length, const remote::file_handle &handle) override
|
||||||
;*/
|
;*/
|
||||||
|
|
||||||
[[nodiscard]] auto fuse_fgetattr(
|
[[nodiscard]] auto fuse_fgetattr(const char *path, remote::stat &r_stat,
|
||||||
const char *path, remote::stat &r_stat, bool &directory,
|
bool &directory,
|
||||||
const remote::file_handle &handle) -> packet::error_type override;
|
const remote::file_handle &handle)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto fuse_fsetattr_x(
|
[[nodiscard]] auto fuse_fsetattr_x(const char *path,
|
||||||
const char *path, const remote::setattr_x &attr,
|
const remote::setattr_x &attr,
|
||||||
const remote::file_handle &handle) -> packet::error_type override;
|
const remote::file_handle &handle)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto fuse_fsync(const char *path, const std::int32_t &datasync,
|
||||||
fuse_fsync(const char *path, const std::int32_t &datasync,
|
const remote::file_handle &handle)
|
||||||
const remote::file_handle &handle) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto fuse_ftruncate(
|
[[nodiscard]] auto fuse_ftruncate(const char *path,
|
||||||
const char *path, const remote::file_offset &size,
|
const remote::file_offset &size,
|
||||||
const remote::file_handle &handle) -> packet::error_type override;
|
const remote::file_handle &handle)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto fuse_getattr(const char *path, remote::stat &r_stat,
|
||||||
fuse_getattr(const char *path, remote::stat &r_stat,
|
bool &directory)
|
||||||
bool &directory) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
/*[[nodiscard]] packet::error_type fuse_getxattr(const char *path, const char
|
/*[[nodiscard]] packet::error_type fuse_getxattr(const char *path, const char
|
||||||
*name, char *value, const remote::file_size &size) override ;
|
*name, char *value, const remote::file_size &size) override ;
|
||||||
@ -115,9 +118,10 @@ public:
|
|||||||
*name, char *value, const remote::file_size &size, std::uint32_t position)
|
*name, char *value, const remote::file_size &size, std::uint32_t position)
|
||||||
override ;*/
|
override ;*/
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto fuse_getxtimes(const char *path,
|
||||||
fuse_getxtimes(const char *path, remote::file_time &bkuptime,
|
remote::file_time &bkuptime,
|
||||||
remote::file_time &crtime) -> packet::error_type override;
|
remote::file_time &crtime)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto fuse_init() -> packet::error_type override;
|
[[nodiscard]] auto fuse_init() -> packet::error_type override;
|
||||||
|
|
||||||
@ -125,28 +129,30 @@ public:
|
|||||||
*buffer, const remote::file_size &size) override ;*/
|
*buffer, const remote::file_size &size) override ;*/
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto
|
||||||
fuse_mkdir(const char *path,
|
fuse_mkdir(const char *path, const remote::file_mode &mode)
|
||||||
const remote::file_mode &mode) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto fuse_open(const char *path,
|
||||||
fuse_open(const char *path, const remote::open_flags &flags,
|
const remote::open_flags &flags,
|
||||||
remote::file_handle &handle) -> packet::error_type override;
|
remote::file_handle &handle)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto fuse_opendir(const char *path, remote::file_handle &handle)
|
[[nodiscard]] auto fuse_opendir(const char *path, remote::file_handle &handle)
|
||||||
-> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto fuse_read(const char *path, char *buffer,
|
||||||
fuse_read(const char *path, char *buffer, const remote::file_size &read_size,
|
const remote::file_size &read_size,
|
||||||
const remote::file_offset &read_offset,
|
const remote::file_offset &read_offset,
|
||||||
const remote::file_handle &handle) -> packet::error_type override;
|
const remote::file_handle &handle)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto fuse_rename(const char *from,
|
[[nodiscard]] auto fuse_rename(const char *from, const char *to)
|
||||||
const char *to) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto
|
||||||
fuse_readdir(const char *path, const remote::file_offset &offset,
|
fuse_readdir(const char *path, const remote::file_offset &offset,
|
||||||
const remote::file_handle &handle,
|
const remote::file_handle &handle, std::string &item_path)
|
||||||
std::string &item_path) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto fuse_release(const char *path,
|
[[nodiscard]] auto fuse_release(const char *path,
|
||||||
const remote::file_handle &handle)
|
const remote::file_handle &handle)
|
||||||
@ -160,8 +166,8 @@ public:
|
|||||||
* char *name) override
|
* char *name) override
|
||||||
* ;*/
|
* ;*/
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto fuse_rmdir(const char *path)
|
||||||
fuse_rmdir(const char *path) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto fuse_setattr_x(const char *path, remote::setattr_x &attr)
|
[[nodiscard]] auto fuse_setattr_x(const char *path, remote::setattr_x &attr)
|
||||||
-> packet::error_type override;
|
-> packet::error_type override;
|
||||||
@ -178,8 +184,8 @@ public:
|
|||||||
const remote::file_time &crtime)
|
const remote::file_time &crtime)
|
||||||
-> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto fuse_setvolname(const char *volname)
|
||||||
fuse_setvolname(const char *volname) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
/*[[nodiscard]] packet::error_type fuse_setxattr(const char *path, const char
|
/*[[nodiscard]] packet::error_type fuse_setxattr(const char *path, const char
|
||||||
*name, const char *value, const remote::file_size &size, const std::int32_t
|
*name, const char *value, const remote::file_size &size, const std::int32_t
|
||||||
@ -189,67 +195,70 @@ public:
|
|||||||
char *name, const char *value, const remote::file_size &size, const
|
char *name, const char *value, const remote::file_size &size, const
|
||||||
std::int32_t &flags, std::uint32_t position) override ;*/
|
std::int32_t &flags, std::uint32_t position) override ;*/
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto fuse_statfs(const char *path, std::uint64_t frsize,
|
||||||
fuse_statfs(const char *path, std::uint64_t frsize,
|
remote::statfs &r_stat)
|
||||||
remote::statfs &r_stat) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto fuse_statfs_x(const char *path, std::uint64_t bsize,
|
||||||
fuse_statfs_x(const char *path, std::uint64_t bsize,
|
remote::statfs_x &r_stat)
|
||||||
remote::statfs_x &r_stat) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto fuse_truncate(const char *path,
|
||||||
fuse_truncate(const char *path,
|
const remote::file_offset &size)
|
||||||
const remote::file_offset &size) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto fuse_unlink(const char *path)
|
||||||
fuse_unlink(const char *path) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto fuse_utimens(const char *path, const remote::file_time *tv,
|
||||||
fuse_utimens(const char *path, const remote::file_time *tv, std::uint64_t op0,
|
std::uint64_t op0, std::uint64_t op1)
|
||||||
std::uint64_t op1) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto fuse_write(const char *path, const char *buffer,
|
||||||
fuse_write(const char *path, const char *buffer,
|
|
||||||
const remote::file_size &write_size,
|
const remote::file_size &write_size,
|
||||||
const remote::file_offset &write_offset,
|
const remote::file_offset &write_offset,
|
||||||
const remote::file_handle &handle) -> packet::error_type override;
|
const remote::file_handle &handle)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto fuse_write_base64(
|
[[nodiscard]] auto fuse_write_base64(const char *path, const char *buffer,
|
||||||
const char *path, const char *buffer, const remote::file_size &write_size,
|
const remote::file_size &write_size,
|
||||||
const remote::file_offset &write_offset,
|
const remote::file_offset &write_offset,
|
||||||
const remote::file_handle &handle) -> packet::error_type override;
|
const remote::file_handle &handle)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
void set_fuse_uid_gid(const remote::user_id &,
|
void set_fuse_uid_gid(const remote::user_id &,
|
||||||
const remote::group_id &) override {}
|
const remote::group_id &) override {}
|
||||||
|
|
||||||
// JSON Layer
|
// JSON Layer
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto winfsp_get_dir_buffer(PVOID /*file_desc*/,
|
||||||
winfsp_get_dir_buffer(PVOID /*file_desc*/,
|
PVOID *& /*ptr*/)
|
||||||
PVOID *& /*ptr*/) -> packet::error_type override {
|
-> packet::error_type override {
|
||||||
return static_cast<packet::error_type>(STATUS_INVALID_HANDLE);
|
return static_cast<packet::error_type>(STATUS_INVALID_HANDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto json_create_directory_snapshot(
|
[[nodiscard]] auto json_create_directory_snapshot(const std::string &path,
|
||||||
const std::string &path, json &json_data) -> packet::error_type override;
|
json &json_data)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto json_read_directory_snapshot(
|
[[nodiscard]] auto json_read_directory_snapshot(
|
||||||
const std::string &path, const remote::file_handle &handle,
|
const std::string &path, const remote::file_handle &handle,
|
||||||
std::uint32_t page, json &json_data) -> packet::error_type override;
|
std::uint32_t page, json &json_data) -> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto json_release_directory_snapshot(
|
[[nodiscard]] auto
|
||||||
const std::string &path,
|
json_release_directory_snapshot(const std::string &path,
|
||||||
const remote::file_handle &handle) -> packet::error_type override;
|
const remote::file_handle &handle)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
// WinFSP Layer
|
// WinFSP Layer
|
||||||
[[nodiscard]] auto winfsp_can_delete(PVOID file_desc, PWSTR file_name)
|
[[nodiscard]] auto winfsp_can_delete(PVOID file_desc, PWSTR file_name)
|
||||||
-> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto winfsp_cleanup(PVOID file_desc, PWSTR file_name,
|
||||||
winfsp_cleanup(PVOID file_desc, PWSTR file_name, UINT32 flags,
|
UINT32 flags, BOOLEAN &was_deleted)
|
||||||
BOOLEAN &was_closed) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto winfsp_close(PVOID file_desc)
|
||||||
winfsp_close(PVOID file_desc) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto
|
||||||
winfsp_create(PWSTR file_name, UINT32 create_options, UINT32 granted_access,
|
winfsp_create(PWSTR file_name, UINT32 create_options, UINT32 granted_access,
|
||||||
@ -264,57 +273,63 @@ public:
|
|||||||
remote::file_info *file_info)
|
remote::file_info *file_info)
|
||||||
-> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto winfsp_get_security_by_name(
|
[[nodiscard]] auto
|
||||||
PWSTR file_name, PUINT32 attributes,
|
winfsp_get_security_by_name(PWSTR file_name, PUINT32 attributes,
|
||||||
std::uint64_t * /*security_descriptor_size*/,
|
std::uint64_t * /*security_descriptor_size*/,
|
||||||
std::wstring & /*str_descriptor*/) -> packet::error_type override;
|
std::wstring & /*str_descriptor*/)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto winfsp_get_volume_info(
|
[[nodiscard]] auto winfsp_get_volume_info(UINT64 &total_size,
|
||||||
UINT64 &total_size, UINT64 &free_size,
|
UINT64 &free_size,
|
||||||
std::string &volume_label) -> packet::error_type override;
|
std::string &volume_label)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto winfsp_mounted(const std::wstring &location)
|
||||||
winfsp_mounted(const std::wstring &location) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto winfsp_open(PWSTR file_name, UINT32 create_options,
|
||||||
winfsp_open(PWSTR file_name, UINT32 create_options, UINT32 granted_access,
|
UINT32 granted_access, PVOID *file_desc,
|
||||||
PVOID *file_desc, remote::file_info *file_info,
|
remote::file_info *file_info,
|
||||||
std::string &normalized_name) -> packet::error_type override;
|
std::string &normalized_name)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto winfsp_overwrite(PVOID file_desc, UINT32 attributes,
|
||||||
winfsp_overwrite(PVOID file_desc, UINT32 attributes,
|
BOOLEAN replace_attributes,
|
||||||
BOOLEAN replace_attributes, UINT64 /*allocation_size*/,
|
UINT64 /*allocation_size*/,
|
||||||
remote::file_info *file_info) -> packet::error_type override;
|
remote::file_info *file_info)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset,
|
||||||
winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
|
UINT32 length, PUINT32 bytes_transferred)
|
||||||
PUINT32 bytes_transferred) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto winfsp_read_directory(PVOID file_desc, PWSTR /*pattern*/,
|
||||||
winfsp_read_directory(PVOID file_desc, PWSTR /*pattern*/, PWSTR marker,
|
PWSTR marker, json &itemList)
|
||||||
json &itemList) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto winfsp_rename(PVOID /*file_desc*/, PWSTR file_name,
|
||||||
winfsp_rename(PVOID /*file_desc*/, PWSTR file_name, PWSTR new_file_name,
|
PWSTR new_file_name,
|
||||||
BOOLEAN replace_if_exists) -> packet::error_type override;
|
BOOLEAN replace_if_exists)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto winfsp_set_basic_info(
|
[[nodiscard]] auto winfsp_set_basic_info(
|
||||||
PVOID file_desc, UINT32 attributes, UINT64 creation_time,
|
PVOID file_desc, UINT32 attributes, UINT64 creation_time,
|
||||||
UINT64 last_access_time, UINT64 last_write_time, UINT64 change_time,
|
UINT64 last_access_time, UINT64 last_write_time, UINT64 change_time,
|
||||||
remote::file_info *file_info) -> packet::error_type override;
|
remote::file_info *file_info) -> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto winfsp_set_file_size(
|
[[nodiscard]] auto winfsp_set_file_size(PVOID file_desc, UINT64 new_size,
|
||||||
PVOID file_desc, UINT64 new_size, BOOLEAN set_allocation_size,
|
BOOLEAN set_allocation_size,
|
||||||
remote::file_info *file_info) -> packet::error_type override;
|
remote::file_info *file_info)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto winfsp_unmounted(const std::wstring &location)
|
||||||
winfsp_unmounted(const std::wstring &location) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto
|
||||||
winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
|
winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
|
||||||
BOOLEAN write_to_end, BOOLEAN constrained_io,
|
BOOLEAN write_to_end, BOOLEAN constrained_io,
|
||||||
PUINT32 bytes_transferred,
|
PUINT32 bytes_transferred, remote::file_info *file_info)
|
||||||
remote::file_info *file_info) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
};
|
};
|
||||||
} // namespace remote_fuse
|
} // namespace remote_fuse
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
@ -33,25 +33,32 @@ protected:
|
|||||||
virtual ~remote_open_file_table() = default;
|
virtual ~remote_open_file_table() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct compat_open_info {
|
struct compat_open_info final {
|
||||||
std::size_t count{0U};
|
|
||||||
std::string client_id;
|
std::string client_id;
|
||||||
|
std::vector<remote::file_handle> handles;
|
||||||
std::string path;
|
std::string path;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct open_info {
|
struct open_info final {
|
||||||
std::size_t count{0U};
|
|
||||||
std::string client_id;
|
std::string client_id;
|
||||||
PVOID directory_buffer{nullptr};
|
PVOID directory_buffer{nullptr};
|
||||||
|
std::vector<native_handle> handles;
|
||||||
std::string path;
|
std::string path;
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<remote::file_handle, compat_open_info> compat_lookup_;
|
std::unordered_map<std::string, std::unique_ptr<compat_open_info>>
|
||||||
std::recursive_mutex compat_mutex_;
|
compat_file_lookup_;
|
||||||
|
std::unordered_map<remote::file_handle, std::string> compat_handle_lookup_;
|
||||||
|
|
||||||
|
private:
|
||||||
std::unordered_map<std::string, std::vector<std::uint64_t>> directory_lookup_;
|
std::unordered_map<std::string, std::vector<std::uint64_t>> directory_lookup_;
|
||||||
std::recursive_mutex directory_mutex_;
|
|
||||||
std::unordered_map<native_handle, open_info> file_lookup_;
|
private:
|
||||||
|
std::unordered_map<std::string, std::unique_ptr<open_info>> file_lookup_;
|
||||||
|
std::unordered_map<native_handle, std::string> handle_lookup_;
|
||||||
|
|
||||||
|
private:
|
||||||
mutable std::recursive_mutex file_mutex_;
|
mutable std::recursive_mutex file_mutex_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -64,11 +71,11 @@ protected:
|
|||||||
PVOID *&buffer) -> bool;
|
PVOID *&buffer) -> bool;
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto get_open_file_path(const native_handle &handle)
|
||||||
get_open_file_path(const native_handle &handle) -> std::string;
|
-> std::string;
|
||||||
|
|
||||||
[[nodiscard]] auto get_open_info(const native_handle &handle,
|
[[nodiscard]] auto get_open_info(const native_handle &handle, open_info &oi)
|
||||||
open_info &oi) -> bool;
|
-> bool;
|
||||||
|
|
||||||
[[nodiscard]] auto has_open_directory(const std::string &client_id,
|
[[nodiscard]] auto has_open_directory(const std::string &client_id,
|
||||||
std::uint64_t handle) -> bool;
|
std::uint64_t handle) -> bool;
|
||||||
@ -77,20 +84,21 @@ protected:
|
|||||||
int error_return) -> int;
|
int error_return) -> int;
|
||||||
|
|
||||||
template <typename error_type>
|
template <typename error_type>
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto has_open_info(const native_handle &handle,
|
||||||
has_open_info(const native_handle &handle,
|
const error_type &error_return)
|
||||||
const error_type &error_return) -> error_type {
|
-> error_type {
|
||||||
recur_mutex_lock file_lock(file_mutex_);
|
recur_mutex_lock file_lock(file_mutex_);
|
||||||
return ((file_lookup_.find(handle) == file_lookup_.end()) ? error_return
|
return handle_lookup_.contains(handle) ? 0 : error_return;
|
||||||
: 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove_all(const std::string &file_path);
|
void remove_all(const std::string &file_path);
|
||||||
|
|
||||||
|
void remove_and_close_all(const native_handle &handle);
|
||||||
|
|
||||||
void remove_compat_open_info(const remote::file_handle &handle);
|
void remove_compat_open_info(const remote::file_handle &handle);
|
||||||
|
|
||||||
auto remove_directory(const std::string &client_id,
|
auto remove_directory(const std::string &client_id, std::uint64_t handle)
|
||||||
std::uint64_t handle) -> bool;
|
-> bool;
|
||||||
|
|
||||||
void remove_open_info(const native_handle &handle);
|
void remove_open_info(const native_handle &handle);
|
||||||
|
|
||||||
@ -102,11 +110,11 @@ protected:
|
|||||||
void set_compat_open_info(const remote::file_handle &handle,
|
void set_compat_open_info(const remote::file_handle &handle,
|
||||||
const std::string &file_path);
|
const std::string &file_path);
|
||||||
|
|
||||||
void set_open_info(const native_handle &handle, open_info oi);
|
void set_open_info(const native_handle &handle, open_info op_info);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto get_open_file_count(const std::string &file_path) const
|
||||||
get_open_file_count(const std::string &file_path) const -> std::size_t;
|
-> std::size_t;
|
||||||
};
|
};
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
#include "drives/fuse/remotefuse/i_remote_instance.hpp"
|
#include "drives/fuse/remotefuse/i_remote_instance.hpp"
|
||||||
#include "drives/remote/remote_open_file_table.hpp"
|
#include "drives/remote/remote_open_file_table.hpp"
|
||||||
#include "drives/winfsp/remotewinfsp/i_remote_instance.hpp"
|
#include "drives/winfsp/remotewinfsp/i_remote_instance.hpp"
|
||||||
|
#include "events/event_system.hpp"
|
||||||
|
#include "events/events.hpp"
|
||||||
#include "types/remote.hpp"
|
#include "types/remote.hpp"
|
||||||
#include "types/repertory.hpp"
|
#include "types/repertory.hpp"
|
||||||
#include "utils/base64.hpp"
|
#include "utils/base64.hpp"
|
||||||
@ -52,7 +54,7 @@ public:
|
|||||||
: config_(config),
|
: config_(config),
|
||||||
drive_(drv),
|
drive_(drv),
|
||||||
mount_location_(std::move(mount_location)),
|
mount_location_(std::move(mount_location)),
|
||||||
client_pool_(config.get_remote_client_pool_size()) {
|
client_pool_(config.get_remote_mount().client_pool_size) {
|
||||||
event_system::instance().raise<service_started>("remote_server_base");
|
event_system::instance().raise<service_started>("remote_server_base");
|
||||||
handler_lookup_.insert(
|
handler_lookup_.insert(
|
||||||
{"::winfsp_can_delete",
|
{"::winfsp_can_delete",
|
||||||
@ -85,10 +87,10 @@ public:
|
|||||||
UINT32 flags{};
|
UINT32 flags{};
|
||||||
DECODE_OR_RETURN(request, flags);
|
DECODE_OR_RETURN(request, flags);
|
||||||
|
|
||||||
BOOLEAN was_closed{};
|
BOOLEAN was_deleted{};
|
||||||
ret = this->winfsp_cleanup(file_desc, file_name.data(), flags,
|
ret = this->winfsp_cleanup(file_desc, file_name.data(), flags,
|
||||||
was_closed);
|
was_deleted);
|
||||||
response.encode(was_closed);
|
response.encode(was_deleted);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}});
|
}});
|
||||||
@ -137,12 +139,12 @@ public:
|
|||||||
if (ret == STATUS_SUCCESS) {
|
if (ret == STATUS_SUCCESS) {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
this->set_client_id(file_desc, client_id);
|
this->set_client_id(file_desc, client_id);
|
||||||
#else
|
#else // !defined(_WIN32)
|
||||||
this->set_client_id(
|
this->set_client_id(
|
||||||
static_cast<native_handle>(
|
static_cast<native_handle>(
|
||||||
reinterpret_cast<std::uintptr_t>(file_desc)),
|
reinterpret_cast<std::uintptr_t>(file_desc)),
|
||||||
client_id);
|
client_id);
|
||||||
#endif
|
#endif // defined(_WIN32)
|
||||||
response.encode(file_desc);
|
response.encode(file_desc);
|
||||||
response.encode(file_info);
|
response.encode(file_info);
|
||||||
response.encode(normalized_name);
|
response.encode(normalized_name);
|
||||||
@ -277,12 +279,12 @@ public:
|
|||||||
if (ret == STATUS_SUCCESS) {
|
if (ret == STATUS_SUCCESS) {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
this->set_client_id(file_desc, client_id);
|
this->set_client_id(file_desc, client_id);
|
||||||
#else
|
#else // !defined(_WIN32)
|
||||||
this->set_client_id(
|
this->set_client_id(
|
||||||
static_cast<native_handle>(
|
static_cast<native_handle>(
|
||||||
reinterpret_cast<std::uintptr_t>(file_desc)),
|
reinterpret_cast<std::uintptr_t>(file_desc)),
|
||||||
client_id);
|
client_id);
|
||||||
#endif
|
#endif // defined(_WIN32)
|
||||||
response.encode(file_desc);
|
response.encode(file_desc);
|
||||||
response.encode(file_info);
|
response.encode(file_info);
|
||||||
response.encode(normalized_name);
|
response.encode(normalized_name);
|
||||||
@ -585,9 +587,9 @@ public:
|
|||||||
0) {
|
0) {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
this->set_compat_client_id(handle, client_id);
|
this->set_compat_client_id(handle, client_id);
|
||||||
#else
|
#else // !defined(_WIN32)
|
||||||
this->set_client_id(static_cast<native_handle>(handle), client_id);
|
this->set_client_id(static_cast<native_handle>(handle), client_id);
|
||||||
#endif
|
#endif // defined(_WIN32)
|
||||||
response.encode(handle);
|
response.encode(handle);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@ -841,9 +843,9 @@ public:
|
|||||||
if ((ret = this->fuse_open(path.c_str(), flags, handle)) >= 0) {
|
if ((ret = this->fuse_open(path.c_str(), flags, handle)) >= 0) {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
this->set_compat_client_id(handle, client_id);
|
this->set_compat_client_id(handle, client_id);
|
||||||
#else
|
#else // !defined(_WIN32)
|
||||||
this->set_client_id(static_cast<native_handle>(handle), client_id);
|
this->set_client_id(static_cast<native_handle>(handle), client_id);
|
||||||
#endif
|
#endif // defined(_WIN32)
|
||||||
response.encode(handle);
|
response.encode(handle);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@ -1357,7 +1359,8 @@ public:
|
|||||||
}});
|
}});
|
||||||
|
|
||||||
packet_server_ = std::make_unique<packet_server>(
|
packet_server_ = std::make_unique<packet_server>(
|
||||||
config_.get_remote_port(), config_.get_remote_token(), 10,
|
config_.get_remote_mount().api_port,
|
||||||
|
config_.get_remote_mount().encryption_token, 10,
|
||||||
[this](const std::string &client_id) {
|
[this](const std::string &client_id) {
|
||||||
return this->closed_handler(client_id);
|
return this->closed_handler(client_id);
|
||||||
},
|
},
|
||||||
|
@ -31,22 +31,25 @@ class i_winfsp_drive {
|
|||||||
INTERFACE_SETUP(i_winfsp_drive);
|
INTERFACE_SETUP(i_winfsp_drive);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] virtual auto get_directory_item_count(
|
[[nodiscard]] virtual auto
|
||||||
const std::string &api_path) const -> std::uint64_t = 0;
|
get_directory_item_count(const std::string &api_path) const
|
||||||
|
-> std::uint64_t = 0;
|
||||||
[[nodiscard]] virtual auto get_directory_items(
|
|
||||||
const std::string &api_path) const -> directory_item_list = 0;
|
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto
|
||||||
get_file_size(const std::string &api_path) const -> std::uint64_t = 0;
|
get_directory_items(const std::string &api_path) const
|
||||||
|
-> directory_item_list = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto get_file_size(const std::string &api_path) const
|
||||||
get_item_meta(const std::string &api_path, const std::string &name,
|
-> std::uint64_t = 0;
|
||||||
std::string &value) const -> api_error = 0;
|
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto get_item_meta(const std::string &api_path,
|
||||||
get_item_meta(const std::string &api_path,
|
const std::string &name,
|
||||||
api_meta_map &meta) const -> api_error = 0;
|
std::string &value) const
|
||||||
|
-> api_error = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_item_meta(const std::string &api_path,
|
||||||
|
api_meta_map &meta) const
|
||||||
|
-> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto
|
||||||
get_security_by_name(PWSTR file_name, PUINT32 attributes,
|
get_security_by_name(PWSTR file_name, PUINT32 attributes,
|
||||||
@ -62,9 +65,9 @@ public:
|
|||||||
virtual void get_volume_info(UINT64 &total_size, UINT64 &free_size,
|
virtual void get_volume_info(UINT64 &total_size, UINT64 &free_size,
|
||||||
std::string &volume_label) const = 0;
|
std::string &volume_label) const = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto populate_file_info(const std::string &api_path,
|
||||||
populate_file_info(const std::string &api_path,
|
remote::file_info &fi) const
|
||||||
remote::file_info &fi) -> api_error = 0;
|
-> api_error = 0;
|
||||||
};
|
};
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
|
||||||
|
@ -29,11 +29,11 @@ class i_remote_instance : public virtual i_remote_json {
|
|||||||
INTERFACE_SETUP(i_remote_instance);
|
INTERFACE_SETUP(i_remote_instance);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual auto winfsp_can_delete(PVOID file_desc,
|
virtual auto winfsp_can_delete(PVOID file_desc, PWSTR file_name)
|
||||||
PWSTR file_name) -> packet::error_type = 0;
|
-> packet::error_type = 0;
|
||||||
|
|
||||||
virtual auto winfsp_cleanup(PVOID file_desc, PWSTR file_name, UINT32 flags,
|
virtual auto winfsp_cleanup(PVOID file_desc, PWSTR file_name, UINT32 flags,
|
||||||
BOOLEAN &was_closed) -> packet::error_type = 0;
|
BOOLEAN &was_deleted) -> packet::error_type = 0;
|
||||||
|
|
||||||
virtual auto winfsp_close(PVOID file_desc) -> packet::error_type = 0;
|
virtual auto winfsp_close(PVOID file_desc) -> packet::error_type = 0;
|
||||||
|
|
||||||
@ -41,72 +41,76 @@ public:
|
|||||||
UINT32 granted_access, UINT32 file_attributes,
|
UINT32 granted_access, UINT32 file_attributes,
|
||||||
UINT64 allocation_size, PVOID *file_desc,
|
UINT64 allocation_size, PVOID *file_desc,
|
||||||
remote::file_info *file_info,
|
remote::file_info *file_info,
|
||||||
std::string &normalized_name,
|
std::string &normalized_name, BOOLEAN &exists)
|
||||||
BOOLEAN &exists) -> packet::error_type = 0;
|
-> packet::error_type = 0;
|
||||||
|
|
||||||
virtual auto winfsp_flush(PVOID file_desc, remote::file_info *file_info)
|
virtual auto winfsp_flush(PVOID file_desc, remote::file_info *file_info)
|
||||||
-> packet::error_type = 0;
|
-> packet::error_type = 0;
|
||||||
|
|
||||||
virtual auto winfsp_get_dir_buffer(PVOID file_desc,
|
virtual auto winfsp_get_dir_buffer(PVOID file_desc, PVOID *&ptr)
|
||||||
PVOID *&ptr) -> packet::error_type = 0;
|
-> packet::error_type = 0;
|
||||||
|
|
||||||
|
virtual auto winfsp_get_file_info(PVOID file_desc,
|
||||||
|
remote::file_info *file_info)
|
||||||
|
-> packet::error_type = 0;
|
||||||
|
|
||||||
virtual auto
|
virtual auto
|
||||||
winfsp_get_file_info(PVOID file_desc,
|
winfsp_get_security_by_name(PWSTR file_name, PUINT32 file_attributes,
|
||||||
remote::file_info *file_info) -> packet::error_type = 0;
|
|
||||||
|
|
||||||
virtual auto winfsp_get_security_by_name(
|
|
||||||
PWSTR file_name, PUINT32 file_attributes,
|
|
||||||
std::uint64_t *security_descriptor_size,
|
std::uint64_t *security_descriptor_size,
|
||||||
std::wstring &str_descriptor) -> packet::error_type = 0;
|
std::wstring &str_descriptor)
|
||||||
|
-> packet::error_type = 0;
|
||||||
|
|
||||||
virtual auto
|
virtual auto winfsp_get_volume_info(UINT64 &total_size, UINT64 &free_size,
|
||||||
winfsp_get_volume_info(UINT64 &total_size, UINT64 &free_size,
|
std::string &volume_label)
|
||||||
std::string &volume_label) -> packet::error_type = 0;
|
-> packet::error_type = 0;
|
||||||
|
|
||||||
virtual auto
|
virtual auto winfsp_mounted(const std::wstring &location)
|
||||||
winfsp_mounted(const std::wstring &location) -> packet::error_type = 0;
|
-> packet::error_type = 0;
|
||||||
|
|
||||||
virtual auto
|
virtual auto winfsp_open(PWSTR file_name, UINT32 create_options,
|
||||||
winfsp_open(PWSTR file_name, UINT32 create_options, UINT32 granted_access,
|
UINT32 granted_access, PVOID *file_desc,
|
||||||
PVOID *file_desc, remote::file_info *file_info,
|
remote::file_info *file_info,
|
||||||
std::string &normalized_name) -> packet::error_type = 0;
|
std::string &normalized_name)
|
||||||
|
-> packet::error_type = 0;
|
||||||
|
|
||||||
virtual auto
|
virtual auto winfsp_overwrite(PVOID file_desc, UINT32 file_attributes,
|
||||||
winfsp_overwrite(PVOID file_desc, UINT32 file_attributes,
|
BOOLEAN replace_file_attributes,
|
||||||
BOOLEAN replace_file_attributes, UINT64 allocation_size,
|
UINT64 allocation_size,
|
||||||
remote::file_info *file_info) -> packet::error_type = 0;
|
remote::file_info *file_info)
|
||||||
|
-> packet::error_type = 0;
|
||||||
|
|
||||||
virtual auto winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset,
|
virtual auto winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset,
|
||||||
UINT32 length,
|
UINT32 length, PUINT32 bytes_transferred)
|
||||||
PUINT32 bytes_transferred) -> packet::error_type = 0;
|
-> packet::error_type = 0;
|
||||||
|
|
||||||
virtual auto winfsp_read_directory(PVOID file_desc, PWSTR pattern,
|
virtual auto winfsp_read_directory(PVOID file_desc, PWSTR pattern,
|
||||||
PWSTR marker,
|
PWSTR marker, json &itemList)
|
||||||
json &itemList) -> packet::error_type = 0;
|
-> packet::error_type = 0;
|
||||||
|
|
||||||
virtual auto
|
virtual auto winfsp_rename(PVOID file_desc, PWSTR file_name,
|
||||||
winfsp_rename(PVOID file_desc, PWSTR file_name, PWSTR new_file_name,
|
PWSTR new_file_name, BOOLEAN replace_if_exists)
|
||||||
BOOLEAN replace_if_exists) -> packet::error_type = 0;
|
-> packet::error_type = 0;
|
||||||
|
|
||||||
virtual auto
|
virtual auto winfsp_set_basic_info(PVOID file_desc, UINT32 file_attributes,
|
||||||
winfsp_set_basic_info(PVOID file_desc, UINT32 file_attributes,
|
UINT64 creation_time,
|
||||||
UINT64 creation_time, UINT64 last_access_time,
|
UINT64 last_access_time,
|
||||||
UINT64 last_write_time, UINT64 change_time,
|
UINT64 last_write_time, UINT64 change_time,
|
||||||
remote::file_info *file_info) -> packet::error_type = 0;
|
remote::file_info *file_info)
|
||||||
|
-> packet::error_type = 0;
|
||||||
|
|
||||||
virtual auto
|
virtual auto winfsp_set_file_size(PVOID file_desc, UINT64 new_size,
|
||||||
winfsp_set_file_size(PVOID file_desc, UINT64 new_size,
|
|
||||||
BOOLEAN set_allocation_size,
|
BOOLEAN set_allocation_size,
|
||||||
remote::file_info *file_info) -> packet::error_type = 0;
|
remote::file_info *file_info)
|
||||||
|
-> packet::error_type = 0;
|
||||||
|
|
||||||
virtual auto
|
virtual auto winfsp_unmounted(const std::wstring &location)
|
||||||
winfsp_unmounted(const std::wstring &location) -> packet::error_type = 0;
|
-> packet::error_type = 0;
|
||||||
|
|
||||||
virtual auto
|
virtual auto winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset,
|
||||||
winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
|
UINT32 length, BOOLEAN write_to_end,
|
||||||
BOOLEAN write_to_end, BOOLEAN constrained_io,
|
BOOLEAN constrained_io, PUINT32 bytes_transferred,
|
||||||
PUINT32 bytes_transferred,
|
remote::file_info *file_info)
|
||||||
remote::file_info *file_info) -> packet::error_type = 0;
|
-> packet::error_type = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
using remote_instance_factory =
|
using remote_instance_factory =
|
||||||
|
@ -50,19 +50,20 @@ public:
|
|||||||
auto json_create_directory_snapshot(const std::string &path, json &json_data)
|
auto json_create_directory_snapshot(const std::string &path, json &json_data)
|
||||||
-> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto json_read_directory_snapshot(
|
auto json_read_directory_snapshot(const std::string &path,
|
||||||
const std::string &path, const remote::file_handle &handle,
|
const remote::file_handle &handle,
|
||||||
std::uint32_t page, json &json_data) -> packet::error_type override;
|
std::uint32_t page, json &json_data)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto json_release_directory_snapshot(const std::string &path,
|
auto json_release_directory_snapshot(const std::string &path,
|
||||||
const remote::file_handle &handle)
|
const remote::file_handle &handle)
|
||||||
-> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto winfsp_can_delete(PVOID file_desc,
|
auto winfsp_can_delete(PVOID file_desc, PWSTR file_name)
|
||||||
PWSTR file_name) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto winfsp_cleanup(PVOID file_desc, PWSTR file_name, UINT32 flags,
|
auto winfsp_cleanup(PVOID file_desc, PWSTR file_name, UINT32 flags,
|
||||||
BOOLEAN &was_closed) -> packet::error_type override;
|
BOOLEAN &was_deleted) -> packet::error_type override;
|
||||||
|
|
||||||
auto winfsp_close(PVOID file_desc) -> packet::error_type override;
|
auto winfsp_close(PVOID file_desc) -> packet::error_type override;
|
||||||
|
|
||||||
@ -75,32 +76,33 @@ public:
|
|||||||
auto winfsp_flush(PVOID file_desc, remote::file_info *file_info)
|
auto winfsp_flush(PVOID file_desc, remote::file_info *file_info)
|
||||||
-> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto winfsp_get_dir_buffer(PVOID file_desc,
|
auto winfsp_get_dir_buffer(PVOID file_desc, PVOID *&ptr)
|
||||||
PVOID *&ptr) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto winfsp_get_file_info(PVOID file_desc, remote::file_info *file_info)
|
auto winfsp_get_file_info(PVOID file_desc, remote::file_info *file_info)
|
||||||
-> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto winfsp_get_security_by_name(
|
auto winfsp_get_security_by_name(PWSTR file_name, PUINT32 attributes,
|
||||||
PWSTR file_name, PUINT32 attributes, std::uint64_t *descriptor_size,
|
std::uint64_t *descriptor_size,
|
||||||
std::wstring &string_descriptor) -> packet::error_type override;
|
std::wstring &string_descriptor)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto winfsp_get_volume_info(UINT64 &total_size, UINT64 &free_size,
|
auto winfsp_get_volume_info(UINT64 &total_size, UINT64 &free_size,
|
||||||
std::string &volume_label)
|
std::string &volume_label)
|
||||||
-> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto
|
auto winfsp_mounted(const std::wstring &location)
|
||||||
winfsp_mounted(const std::wstring &location) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto winfsp_open(PWSTR file_name, UINT32 create_options,
|
auto winfsp_open(PWSTR file_name, UINT32 create_options,
|
||||||
UINT32 granted_access, PVOID *file_desc,
|
UINT32 granted_access, PVOID *file_desc,
|
||||||
remote::file_info *file_info,
|
remote::file_info *file_info, std::string &normalized_name)
|
||||||
std::string &normalized_name) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto
|
auto winfsp_overwrite(PVOID file_desc, UINT32 attributes,
|
||||||
winfsp_overwrite(PVOID file_desc, UINT32 attributes,
|
|
||||||
BOOLEAN replace_attributes, UINT64 allocation_size,
|
BOOLEAN replace_attributes, UINT64 allocation_size,
|
||||||
remote::file_info *file_info) -> packet::error_type override;
|
remote::file_info *file_info)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
|
auto winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
|
||||||
PUINT32 bytes_transferred) -> packet::error_type override;
|
PUINT32 bytes_transferred) -> packet::error_type override;
|
||||||
@ -111,23 +113,24 @@ public:
|
|||||||
auto winfsp_rename(PVOID file_desc, PWSTR file_name, PWSTR new_file_name,
|
auto winfsp_rename(PVOID file_desc, PWSTR file_name, PWSTR new_file_name,
|
||||||
BOOLEAN replace_if_exists) -> packet::error_type override;
|
BOOLEAN replace_if_exists) -> packet::error_type override;
|
||||||
|
|
||||||
auto winfsp_set_basic_info(
|
auto winfsp_set_basic_info(PVOID file_desc, UINT32 attributes,
|
||||||
PVOID file_desc, UINT32 attributes, UINT64 creation_time,
|
UINT64 creation_time, UINT64 last_access_time,
|
||||||
UINT64 last_access_time, UINT64 last_write_time, UINT64 change_time,
|
UINT64 last_write_time, UINT64 change_time,
|
||||||
remote::file_info *file_info) -> packet::error_type override;
|
remote::file_info *file_info)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto winfsp_set_file_size(
|
auto winfsp_set_file_size(PVOID file_desc, UINT64 new_size,
|
||||||
PVOID file_desc, UINT64 new_size, BOOLEAN set_allocation_size,
|
BOOLEAN set_allocation_size,
|
||||||
remote::file_info *file_info) -> packet::error_type override;
|
remote::file_info *file_info)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto
|
auto winfsp_unmounted(const std::wstring &location)
|
||||||
winfsp_unmounted(const std::wstring &location) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto
|
auto winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
|
||||||
winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
|
|
||||||
BOOLEAN write_to_end, BOOLEAN constrained_io,
|
BOOLEAN write_to_end, BOOLEAN constrained_io,
|
||||||
PUINT32 bytes_transferred,
|
PUINT32 bytes_transferred, remote::file_info *file_info)
|
||||||
remote::file_info *file_info) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
};
|
};
|
||||||
} // namespace remote_winfsp
|
} // namespace remote_winfsp
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
@ -49,23 +49,23 @@ private:
|
|||||||
|
|
||||||
[[nodiscard]] auto get_next_handle() -> std::uint64_t;
|
[[nodiscard]] auto get_next_handle() -> std::uint64_t;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto populate_file_info(const std::string &api_path,
|
||||||
populate_file_info(const std::string &api_path,
|
remote::file_info &file_info)
|
||||||
remote::file_info &file_info) -> packet::error_type;
|
-> packet::error_type;
|
||||||
|
|
||||||
void populate_stat(const char *path, bool directory, remote::stat &r_stat,
|
void populate_stat(const char *path, bool directory, remote::stat &r_stat,
|
||||||
const struct _stat64 &unix_st);
|
const struct _stat64 &unix_st);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// FUSE Layer
|
// FUSE Layer
|
||||||
auto fuse_access(const char *path,
|
auto fuse_access(const char *path, const std::int32_t &mask)
|
||||||
const std::int32_t &mask) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto fuse_chflags(const char *path,
|
auto fuse_chflags(const char *path, std::uint32_t flags)
|
||||||
std::uint32_t flags) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto fuse_chmod(const char *path,
|
auto fuse_chmod(const char *path, const remote::file_mode &mode)
|
||||||
const remote::file_mode &mode) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto fuse_chown(const char *path, const remote::user_id &uid,
|
auto fuse_chown(const char *path, const remote::user_id &uid,
|
||||||
const remote::group_id &gid) -> packet::error_type override;
|
const remote::group_id &gid) -> packet::error_type override;
|
||||||
@ -84,16 +84,16 @@ public:
|
|||||||
const remote::file_handle &handle)
|
const remote::file_handle &handle)
|
||||||
-> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto
|
auto fuse_fsync(const char *path, const std::int32_t &datasync,
|
||||||
fuse_fsync(const char *path, const std::int32_t &datasync,
|
const remote::file_handle &handle)
|
||||||
const remote::file_handle &handle) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto fuse_ftruncate(const char *path, const remote::file_offset &size,
|
auto fuse_ftruncate(const char *path, const remote::file_offset &size,
|
||||||
const remote::file_handle &handle)
|
const remote::file_handle &handle)
|
||||||
-> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto fuse_getattr(const char *path, remote::stat &r_stat,
|
auto fuse_getattr(const char *path, remote::stat &r_stat, bool &directory)
|
||||||
bool &directory) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
/*packet::error_type fuse_getxattr(const char *path, const char *name, char
|
/*packet::error_type fuse_getxattr(const char *path, const char *name, char
|
||||||
*value, const remote::file_size &size) override ;
|
*value, const remote::file_size &size) override ;
|
||||||
@ -110,41 +110,43 @@ public:
|
|||||||
const remote::file_size &size) override
|
const remote::file_size &size) override
|
||||||
;*/
|
;*/
|
||||||
|
|
||||||
auto fuse_mkdir(const char *path,
|
auto fuse_mkdir(const char *path, const remote::file_mode &mode)
|
||||||
const remote::file_mode &mode) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto fuse_opendir(const char *path,
|
auto fuse_opendir(const char *path, remote::file_handle &handle)
|
||||||
remote::file_handle &handle) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto fuse_create(const char *path, const remote::file_mode &mode,
|
auto fuse_create(const char *path, const remote::file_mode &mode,
|
||||||
const remote::open_flags &flags,
|
const remote::open_flags &flags, remote::file_handle &handle)
|
||||||
remote::file_handle &handle) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto fuse_open(const char *path, const remote::open_flags &flags,
|
auto fuse_open(const char *path, const remote::open_flags &flags,
|
||||||
remote::file_handle &handle) -> packet::error_type override;
|
remote::file_handle &handle) -> packet::error_type override;
|
||||||
|
|
||||||
auto
|
auto fuse_read(const char *path, char *buffer,
|
||||||
fuse_read(const char *path, char *buffer, const remote::file_size &read_size,
|
const remote::file_size &read_size,
|
||||||
const remote::file_offset &read_offset,
|
const remote::file_offset &read_offset,
|
||||||
const remote::file_handle &handle) -> packet::error_type override;
|
const remote::file_handle &handle)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto fuse_rename(const char *from,
|
auto fuse_rename(const char *from, const char *to)
|
||||||
const char *to) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto
|
auto fuse_write(const char *path, const char *buffer,
|
||||||
fuse_write(const char *path, const char *buffer,
|
|
||||||
const remote::file_size &write_size,
|
const remote::file_size &write_size,
|
||||||
const remote::file_offset &write_offset,
|
const remote::file_offset &write_offset,
|
||||||
const remote::file_handle &handle) -> packet::error_type override;
|
const remote::file_handle &handle)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto fuse_write_base64(
|
auto fuse_write_base64(const char *path, const char *buffer,
|
||||||
const char *path, const char *buffer, const remote::file_size &write_size,
|
const remote::file_size &write_size,
|
||||||
const remote::file_offset &write_offset,
|
const remote::file_offset &write_offset,
|
||||||
const remote::file_handle &handle) -> packet::error_type override;
|
const remote::file_handle &handle)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto fuse_readdir(const char *path, const remote::file_offset &offset,
|
auto fuse_readdir(const char *path, const remote::file_offset &offset,
|
||||||
const remote::file_handle &handle,
|
const remote::file_handle &handle, std::string &item_path)
|
||||||
std::string &item_path) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto fuse_release(const char *path, const remote::file_handle &handle)
|
auto fuse_release(const char *path, const remote::file_handle &handle)
|
||||||
-> packet::error_type override;
|
-> packet::error_type override;
|
||||||
@ -157,8 +159,8 @@ public:
|
|||||||
|
|
||||||
auto fuse_rmdir(const char *path) -> packet::error_type override;
|
auto fuse_rmdir(const char *path) -> packet::error_type override;
|
||||||
|
|
||||||
auto fuse_setattr_x(const char *path,
|
auto fuse_setattr_x(const char *path, remote::setattr_x &attr)
|
||||||
remote::setattr_x &attr) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto fuse_setbkuptime(const char *path, const remote::file_time &bkuptime)
|
auto fuse_setbkuptime(const char *path, const remote::file_time &bkuptime)
|
||||||
-> packet::error_type override;
|
-> packet::error_type override;
|
||||||
@ -191,8 +193,8 @@ public:
|
|||||||
auto fuse_unlink(const char *path) -> packet::error_type override;
|
auto fuse_unlink(const char *path) -> packet::error_type override;
|
||||||
|
|
||||||
auto fuse_utimens(const char *path, const remote::file_time *tv,
|
auto fuse_utimens(const char *path, const remote::file_time *tv,
|
||||||
std::uint64_t op0,
|
std::uint64_t op0, std::uint64_t op1)
|
||||||
std::uint64_t op1) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
void set_fuse_uid_gid(const remote::user_id & /* uid */,
|
void set_fuse_uid_gid(const remote::user_id & /* uid */,
|
||||||
const remote::group_id & /* gid */) override {}
|
const remote::group_id & /* gid */) override {}
|
||||||
@ -201,20 +203,21 @@ public:
|
|||||||
auto json_create_directory_snapshot(const std::string &path, json &json_data)
|
auto json_create_directory_snapshot(const std::string &path, json &json_data)
|
||||||
-> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto json_read_directory_snapshot(
|
auto json_read_directory_snapshot(const std::string &path,
|
||||||
const std::string &path, const remote::file_handle &handle,
|
const remote::file_handle &handle,
|
||||||
std::uint32_t page, json &json_data) -> packet::error_type override;
|
std::uint32_t page, json &json_data)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto json_release_directory_snapshot(const std::string &path,
|
auto json_release_directory_snapshot(const std::string &path,
|
||||||
const remote::file_handle &handle)
|
const remote::file_handle &handle)
|
||||||
-> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
// WinFSP Layer
|
// WinFSP Layer
|
||||||
auto winfsp_can_delete(PVOID file_desc,
|
auto winfsp_can_delete(PVOID file_desc, PWSTR file_name)
|
||||||
PWSTR file_name) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto winfsp_cleanup(PVOID file_desc, PWSTR file_name, UINT32 flags,
|
auto winfsp_cleanup(PVOID file_desc, PWSTR file_name, UINT32 flags,
|
||||||
BOOLEAN &was_closed) -> packet::error_type override;
|
BOOLEAN &was_deleted) -> packet::error_type override;
|
||||||
|
|
||||||
auto winfsp_close(PVOID file_desc) -> packet::error_type override;
|
auto winfsp_close(PVOID file_desc) -> packet::error_type override;
|
||||||
|
|
||||||
@ -227,32 +230,33 @@ public:
|
|||||||
auto winfsp_flush(PVOID file_desc, remote::file_info *file_info)
|
auto winfsp_flush(PVOID file_desc, remote::file_info *file_info)
|
||||||
-> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto winfsp_get_dir_buffer(PVOID file_desc,
|
auto winfsp_get_dir_buffer(PVOID file_desc, PVOID *&ptr)
|
||||||
PVOID *&ptr) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto winfsp_get_file_info(PVOID file_desc, remote::file_info *file_info)
|
auto winfsp_get_file_info(PVOID file_desc, remote::file_info *file_info)
|
||||||
-> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto winfsp_get_security_by_name(
|
auto winfsp_get_security_by_name(PWSTR file_name, PUINT32 attributes,
|
||||||
PWSTR file_name, PUINT32 attributes, std::uint64_t *descriptor_size,
|
std::uint64_t *descriptor_size,
|
||||||
std::wstring &string_descriptor) -> packet::error_type override;
|
std::wstring &string_descriptor)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto winfsp_get_volume_info(UINT64 &total_size, UINT64 &free_size,
|
auto winfsp_get_volume_info(UINT64 &total_size, UINT64 &free_size,
|
||||||
std::string &volume_label)
|
std::string &volume_label)
|
||||||
-> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto
|
auto winfsp_mounted(const std::wstring &location)
|
||||||
winfsp_mounted(const std::wstring &location) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto winfsp_open(PWSTR file_name, UINT32 create_options,
|
auto winfsp_open(PWSTR file_name, UINT32 create_options,
|
||||||
UINT32 granted_access, PVOID *file_desc,
|
UINT32 granted_access, PVOID *file_desc,
|
||||||
remote::file_info *file_info,
|
remote::file_info *file_info, std::string &normalized_name)
|
||||||
std::string &normalized_name) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto
|
auto winfsp_overwrite(PVOID file_desc, UINT32 attributes,
|
||||||
winfsp_overwrite(PVOID file_desc, UINT32 attributes,
|
|
||||||
BOOLEAN replace_attributes, UINT64 allocation_size,
|
BOOLEAN replace_attributes, UINT64 allocation_size,
|
||||||
remote::file_info *file_info) -> packet::error_type override;
|
remote::file_info *file_info)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
|
auto winfsp_read(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
|
||||||
PUINT32 bytes_transferred) -> packet::error_type override;
|
PUINT32 bytes_transferred) -> packet::error_type override;
|
||||||
@ -263,23 +267,24 @@ public:
|
|||||||
auto winfsp_rename(PVOID file_desc, PWSTR file_name, PWSTR new_file_name,
|
auto winfsp_rename(PVOID file_desc, PWSTR file_name, PWSTR new_file_name,
|
||||||
BOOLEAN replace_if_exists) -> packet::error_type override;
|
BOOLEAN replace_if_exists) -> packet::error_type override;
|
||||||
|
|
||||||
auto winfsp_set_basic_info(
|
auto winfsp_set_basic_info(PVOID file_desc, UINT32 attributes,
|
||||||
PVOID file_desc, UINT32 attributes, UINT64 creation_time,
|
UINT64 creation_time, UINT64 last_access_time,
|
||||||
UINT64 last_access_time, UINT64 last_write_time, UINT64 change_time,
|
UINT64 last_write_time, UINT64 change_time,
|
||||||
remote::file_info *file_info) -> packet::error_type override;
|
remote::file_info *file_info)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto winfsp_set_file_size(
|
auto winfsp_set_file_size(PVOID file_desc, UINT64 new_size,
|
||||||
PVOID file_desc, UINT64 new_size, BOOLEAN set_allocation_size,
|
BOOLEAN set_allocation_size,
|
||||||
remote::file_info *file_info) -> packet::error_type override;
|
remote::file_info *file_info)
|
||||||
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto
|
auto winfsp_unmounted(const std::wstring &location)
|
||||||
winfsp_unmounted(const std::wstring &location) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
|
|
||||||
auto
|
auto winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
|
||||||
winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
|
|
||||||
BOOLEAN write_to_end, BOOLEAN constrained_io,
|
BOOLEAN write_to_end, BOOLEAN constrained_io,
|
||||||
PUINT32 bytes_transferred,
|
PUINT32 bytes_transferred, remote::file_info *file_info)
|
||||||
remote::file_info *file_info) -> packet::error_type override;
|
-> packet::error_type override;
|
||||||
};
|
};
|
||||||
} // namespace remote_winfsp
|
} // namespace remote_winfsp
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
@ -50,10 +50,10 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
app_config &config_;
|
app_config &config_;
|
||||||
lock_data &lock_;
|
|
||||||
remote_winfsp_drive &drive_;
|
remote_winfsp_drive &drive_;
|
||||||
const std::vector<std::string> drive_args_;
|
const std::vector<std::string> drive_args_;
|
||||||
FileSystemHost host_;
|
FileSystemHost host_;
|
||||||
|
lock_data &lock_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
auto OnStart(ULONG, PWSTR *) -> NTSTATUS override;
|
auto OnStart(ULONG, PWSTR *) -> NTSTATUS override;
|
||||||
@ -75,8 +75,8 @@ private:
|
|||||||
static void set_file_info(FileInfo &dest, const remote::file_info &src);
|
static void set_file_info(FileInfo &dest, const remote::file_info &src);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
auto CanDelete(PVOID file_node, PVOID file_desc,
|
auto CanDelete(PVOID file_node, PVOID file_desc, PWSTR file_name)
|
||||||
PWSTR file_name) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
VOID Cleanup(PVOID file_node, PVOID file_desc, PWSTR file_name,
|
VOID Cleanup(PVOID file_node, PVOID file_desc, PWSTR file_name,
|
||||||
ULONG flags) override;
|
ULONG flags) override;
|
||||||
@ -88,11 +88,11 @@ public:
|
|||||||
UINT64 allocation_size, PVOID *file_node, PVOID *file_desc,
|
UINT64 allocation_size, PVOID *file_node, PVOID *file_desc,
|
||||||
OpenFileInfo *ofi) -> NTSTATUS override;
|
OpenFileInfo *ofi) -> NTSTATUS override;
|
||||||
|
|
||||||
auto Flush(PVOID file_node, PVOID file_desc,
|
auto Flush(PVOID file_node, PVOID file_desc, FileInfo *file_info)
|
||||||
FileInfo *file_info) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
auto GetFileInfo(PVOID file_node, PVOID file_desc,
|
auto GetFileInfo(PVOID file_node, PVOID file_desc, FileInfo *file_info)
|
||||||
FileInfo *file_info) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
auto GetSecurityByName(PWSTR file_name, PUINT32 attributes,
|
auto GetSecurityByName(PWSTR file_name, PUINT32 attributes,
|
||||||
PSECURITY_DESCRIPTOR descriptor,
|
PSECURITY_DESCRIPTOR descriptor,
|
||||||
@ -107,8 +107,8 @@ public:
|
|||||||
auto Mounted(PVOID host) -> NTSTATUS override;
|
auto Mounted(PVOID host) -> NTSTATUS override;
|
||||||
|
|
||||||
auto Open(PWSTR file_name, UINT32 create_options, UINT32 granted_access,
|
auto Open(PWSTR file_name, UINT32 create_options, UINT32 granted_access,
|
||||||
PVOID *file_node, PVOID *file_desc,
|
PVOID *file_node, PVOID *file_desc, OpenFileInfo *ofi)
|
||||||
OpenFileInfo *ofi) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
auto Overwrite(PVOID file_node, PVOID file_desc, UINT32 attributes,
|
auto Overwrite(PVOID file_node, PVOID file_desc, UINT32 attributes,
|
||||||
BOOLEAN replace_attributes, UINT64 allocation_size,
|
BOOLEAN replace_attributes, UINT64 allocation_size,
|
||||||
@ -122,8 +122,8 @@ public:
|
|||||||
PULONG bytes_transferred) -> NTSTATUS override;
|
PULONG bytes_transferred) -> NTSTATUS override;
|
||||||
|
|
||||||
auto Rename(PVOID file_node, PVOID file_desc, PWSTR file_name,
|
auto Rename(PVOID file_node, PVOID file_desc, PWSTR file_name,
|
||||||
PWSTR new_file_name,
|
PWSTR new_file_name, BOOLEAN replace_if_exists)
|
||||||
BOOLEAN replace_if_exists) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
auto SetBasicInfo(PVOID file_node, PVOID file_desc, UINT32 attributes,
|
auto SetBasicInfo(PVOID file_node, PVOID file_desc, UINT32 attributes,
|
||||||
UINT64 creation_time, UINT64 last_access_time,
|
UINT64 creation_time, UINT64 last_access_time,
|
||||||
@ -131,15 +131,15 @@ public:
|
|||||||
FileInfo *file_info) -> NTSTATUS override;
|
FileInfo *file_info) -> NTSTATUS override;
|
||||||
|
|
||||||
auto SetFileSize(PVOID file_node, PVOID file_desc, UINT64 new_size,
|
auto SetFileSize(PVOID file_node, PVOID file_desc, UINT64 new_size,
|
||||||
BOOLEAN set_allocation_size,
|
BOOLEAN set_allocation_size, FileInfo *file_info)
|
||||||
FileInfo *file_info) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
VOID Unmounted(PVOID host) override;
|
VOID Unmounted(PVOID host) override;
|
||||||
|
|
||||||
auto Write(PVOID file_node, PVOID file_desc, PVOID buffer, UINT64 offset,
|
auto Write(PVOID file_node, PVOID file_desc, PVOID buffer, UINT64 offset,
|
||||||
ULONG length, BOOLEAN write_to_end, BOOLEAN constrained_io,
|
ULONG length, BOOLEAN write_to_end, BOOLEAN constrained_io,
|
||||||
PULONG bytes_transferred,
|
PULONG bytes_transferred, FileInfo *file_info)
|
||||||
FileInfo *file_info) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
void shutdown() { ::GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); }
|
void shutdown() { ::GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); }
|
||||||
|
|
||||||
|
@ -53,11 +53,11 @@ private:
|
|||||||
~winfsp_service() override = default;
|
~winfsp_service() override = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
lock_data &lock_;
|
|
||||||
winfsp_drive &drive_;
|
|
||||||
const std::vector<std::string> drive_args_;
|
|
||||||
FileSystemHost host_;
|
|
||||||
app_config &config_;
|
app_config &config_;
|
||||||
|
winfsp_drive &drive_;
|
||||||
|
std::vector<std::string> drive_args_;
|
||||||
|
FileSystemHost host_;
|
||||||
|
lock_data &lock_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
auto OnStart(ULONG, PWSTR *) -> NTSTATUS override;
|
auto OnStart(ULONG, PWSTR *) -> NTSTATUS override;
|
||||||
@ -75,22 +75,28 @@ private:
|
|||||||
std::unique_ptr<remote_winfsp::remote_server> remote_server_;
|
std::unique_ptr<remote_winfsp::remote_server> remote_server_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static auto
|
[[nodiscard]] auto handle_error(std::string_view function_name,
|
||||||
parse_mount_location(const std::wstring &mount_location) -> std::string;
|
const std::string &api_path, api_error error,
|
||||||
|
FileInfo *file_info, std::uint64_t file_size,
|
||||||
|
bool raise_on_failure_only = false) const
|
||||||
|
-> NTSTATUS;
|
||||||
|
|
||||||
|
static auto parse_mount_location(const std::wstring &mount_location)
|
||||||
|
-> std::string;
|
||||||
|
|
||||||
void populate_file_info(const std::string &api_path, std::uint64_t file_size,
|
void populate_file_info(const std::string &api_path, std::uint64_t file_size,
|
||||||
const api_meta_map &meta,
|
const api_meta_map &meta,
|
||||||
FSP_FSCTL_OPEN_FILE_INFO &ofi);
|
FSP_FSCTL_OPEN_FILE_INFO &ofi) const;
|
||||||
|
|
||||||
void populate_file_info(std::uint64_t file_size, api_meta_map meta,
|
void populate_file_info(std::uint64_t file_size, api_meta_map meta,
|
||||||
FSP_FSCTL_FILE_INFO &fi);
|
FSP_FSCTL_FILE_INFO &fi) const;
|
||||||
|
|
||||||
static void set_file_info(remote::file_info &dest,
|
static void set_file_info(remote::file_info &dest,
|
||||||
const FSP_FSCTL_FILE_INFO &src);
|
const FSP_FSCTL_FILE_INFO &src);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
auto CanDelete(PVOID file_node, PVOID file_desc,
|
auto CanDelete(PVOID file_node, PVOID file_desc, PWSTR file_name)
|
||||||
PWSTR file_name) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
VOID Cleanup(PVOID file_node, PVOID file_desc, PWSTR file_name,
|
VOID Cleanup(PVOID file_node, PVOID file_desc, PWSTR file_name,
|
||||||
ULONG flags) override;
|
ULONG flags) override;
|
||||||
@ -102,8 +108,8 @@ public:
|
|||||||
UINT64 allocation_size, PVOID *file_node, PVOID *file_desc,
|
UINT64 allocation_size, PVOID *file_node, PVOID *file_desc,
|
||||||
OpenFileInfo *ofi) -> NTSTATUS override;
|
OpenFileInfo *ofi) -> NTSTATUS override;
|
||||||
|
|
||||||
auto Flush(PVOID file_node, PVOID file_desc,
|
auto Flush(PVOID file_node, PVOID file_desc, FileInfo *file_info)
|
||||||
FileInfo *file_info) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_directory_item_count(const std::string &api_path) const
|
[[nodiscard]] auto get_directory_item_count(const std::string &api_path) const
|
||||||
-> std::uint64_t override;
|
-> std::uint64_t override;
|
||||||
@ -111,24 +117,25 @@ public:
|
|||||||
[[nodiscard]] auto get_directory_items(const std::string &api_path) const
|
[[nodiscard]] auto get_directory_items(const std::string &api_path) const
|
||||||
-> directory_item_list override;
|
-> directory_item_list override;
|
||||||
|
|
||||||
auto GetFileInfo(PVOID file_node, PVOID file_desc,
|
auto GetFileInfo(PVOID file_node, PVOID file_desc, FileInfo *file_info)
|
||||||
FileInfo *file_info) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto get_file_size(const std::string &api_path) const
|
||||||
get_file_size(const std::string &api_path) const -> std::uint64_t override;
|
-> std::uint64_t override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto get_item_meta(const std::string &api_path,
|
||||||
get_item_meta(const std::string &api_path,
|
api_meta_map &meta) const
|
||||||
api_meta_map &meta) const -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto get_item_meta(const std::string &api_path,
|
||||||
get_item_meta(const std::string &api_path, const std::string &name,
|
const std::string &name,
|
||||||
std::string &value) const -> api_error override;
|
std::string &value) const
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto get_security_by_name(PWSTR file_name, PUINT32 attributes,
|
||||||
get_security_by_name(PWSTR file_name, PUINT32 attributes,
|
|
||||||
PSECURITY_DESCRIPTOR descriptor,
|
PSECURITY_DESCRIPTOR descriptor,
|
||||||
std::uint64_t *descriptor_size) -> NTSTATUS override;
|
std::uint64_t *descriptor_size)
|
||||||
|
-> NTSTATUS override;
|
||||||
|
|
||||||
auto GetSecurityByName(PWSTR file_name, PUINT32 attributes,
|
auto GetSecurityByName(PWSTR file_name, PUINT32 attributes,
|
||||||
PSECURITY_DESCRIPTOR descriptor,
|
PSECURITY_DESCRIPTOR descriptor,
|
||||||
@ -152,16 +159,16 @@ public:
|
|||||||
auto Mounted(PVOID host) -> NTSTATUS override;
|
auto Mounted(PVOID host) -> NTSTATUS override;
|
||||||
|
|
||||||
auto Open(PWSTR file_name, UINT32 create_options, UINT32 granted_access,
|
auto Open(PWSTR file_name, UINT32 create_options, UINT32 granted_access,
|
||||||
PVOID *file_node, PVOID *file_desc,
|
PVOID *file_node, PVOID *file_desc, OpenFileInfo *ofi)
|
||||||
OpenFileInfo *ofi) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
auto Overwrite(PVOID file_node, PVOID file_desc, UINT32 attributes,
|
auto Overwrite(PVOID file_node, PVOID file_desc, UINT32 attributes,
|
||||||
BOOLEAN replace_attributes, UINT64 allocation_size,
|
BOOLEAN replace_attributes, UINT64 allocation_size,
|
||||||
FileInfo *file_info) -> NTSTATUS override;
|
FileInfo *file_info) -> NTSTATUS override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto populate_file_info(const std::string &api_path,
|
||||||
populate_file_info(const std::string &api_path,
|
remote::file_info &file_info) const
|
||||||
remote::file_info &file_info) -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
auto Read(PVOID file_node, PVOID file_desc, PVOID buffer, UINT64 offset,
|
auto Read(PVOID file_node, PVOID file_desc, PVOID buffer, UINT64 offset,
|
||||||
ULONG length, PULONG bytes_transferred) -> NTSTATUS override;
|
ULONG length, PULONG bytes_transferred) -> NTSTATUS override;
|
||||||
@ -171,8 +178,8 @@ public:
|
|||||||
PULONG bytes_transferred) -> NTSTATUS override;
|
PULONG bytes_transferred) -> NTSTATUS override;
|
||||||
|
|
||||||
auto Rename(PVOID file_node, PVOID file_desc, PWSTR file_name,
|
auto Rename(PVOID file_node, PVOID file_desc, PWSTR file_name,
|
||||||
PWSTR new_file_name,
|
PWSTR new_file_name, BOOLEAN replace_if_exists)
|
||||||
BOOLEAN replace_if_exists) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
auto SetBasicInfo(PVOID file_node, PVOID file_desc, UINT32 attributes,
|
auto SetBasicInfo(PVOID file_node, PVOID file_desc, UINT32 attributes,
|
||||||
UINT64 creation_time, UINT64 last_access_time,
|
UINT64 creation_time, UINT64 last_access_time,
|
||||||
@ -180,15 +187,15 @@ public:
|
|||||||
FileInfo *file_info) -> NTSTATUS override;
|
FileInfo *file_info) -> NTSTATUS override;
|
||||||
|
|
||||||
auto SetFileSize(PVOID file_node, PVOID file_desc, UINT64 new_size,
|
auto SetFileSize(PVOID file_node, PVOID file_desc, UINT64 new_size,
|
||||||
BOOLEAN set_allocation_size,
|
BOOLEAN set_allocation_size, FileInfo *file_info)
|
||||||
FileInfo *file_info) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
VOID Unmounted(PVOID host) override;
|
VOID Unmounted(PVOID host) override;
|
||||||
|
|
||||||
auto Write(PVOID file_node, PVOID file_desc, PVOID buffer, UINT64 offset,
|
auto Write(PVOID file_node, PVOID file_desc, PVOID buffer, UINT64 offset,
|
||||||
ULONG length, BOOLEAN write_to_end, BOOLEAN constrained_io,
|
ULONG length, BOOLEAN write_to_end, BOOLEAN constrained_io,
|
||||||
PULONG bytes_transferred,
|
PULONG bytes_transferred, FileInfo *file_info)
|
||||||
FileInfo *file_info) -> NTSTATUS override;
|
-> NTSTATUS override;
|
||||||
|
|
||||||
void shutdown();
|
void shutdown();
|
||||||
|
|
||||||
|
@ -32,9 +32,12 @@ enum class event_level {
|
|||||||
trace,
|
trace,
|
||||||
};
|
};
|
||||||
|
|
||||||
auto event_level_from_string(std::string level) -> event_level;
|
[[nodiscard]] auto
|
||||||
|
event_level_from_string(std::string level,
|
||||||
|
event_level default_level = event_level::info)
|
||||||
|
-> event_level;
|
||||||
|
|
||||||
auto event_level_to_string(event_level level) -> std::string;
|
[[nodiscard]] auto event_level_to_string(event_level level) -> std::string;
|
||||||
|
|
||||||
class event {
|
class event {
|
||||||
protected:
|
protected:
|
||||||
@ -72,4 +75,18 @@ public:
|
|||||||
};
|
};
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
|
||||||
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
|
template <> struct adl_serializer<std::atomic<repertory::event_level>> {
|
||||||
|
static void to_json(json &data,
|
||||||
|
const std::atomic<repertory::event_level> &value) {
|
||||||
|
data = repertory::event_level_to_string(value.load());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void from_json(const json &data,
|
||||||
|
std::atomic<repertory::event_level> &value) {
|
||||||
|
value.store(repertory::event_level_from_string(data.get<std::string>()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|
||||||
#endif // REPERTORY_INCLUDE_EVENTS_EVENT_HPP_
|
#endif // REPERTORY_INCLUDE_EVENTS_EVENT_HPP_
|
||||||
|
@ -44,6 +44,7 @@ using event_consumer = event_system::event_consumer;
|
|||||||
#define E_FROM_STRING(t) t
|
#define E_FROM_STRING(t) t
|
||||||
#define E_FROM_UINT16(t) std::to_string(t)
|
#define E_FROM_UINT16(t) std::to_string(t)
|
||||||
#define E_FROM_UINT64(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) \
|
#define E_PROP(type, name, short_name, ts) \
|
||||||
private: \
|
private: \
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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_CACHE_SIZE_MGR_HPP_
|
||||||
|
#define REPERTORY_INCLUDE_FILE_MANAGER_CACHE_SIZE_MGR_HPP_
|
||||||
|
|
||||||
|
#include "types/repertory.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
class app_config;
|
||||||
|
|
||||||
|
class cache_size_mgr final {
|
||||||
|
public:
|
||||||
|
cache_size_mgr(const cache_size_mgr &) = delete;
|
||||||
|
cache_size_mgr(cache_size_mgr &&) = delete;
|
||||||
|
auto operator=(const cache_size_mgr &) -> cache_size_mgr & = delete;
|
||||||
|
auto operator=(cache_size_mgr &&) -> cache_size_mgr & = delete;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
cache_size_mgr() = default;
|
||||||
|
|
||||||
|
~cache_size_mgr() { stop(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static cache_size_mgr instance_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
app_config *cfg_{nullptr};
|
||||||
|
std::uint64_t cache_size_{0U};
|
||||||
|
mutable std::mutex mtx_;
|
||||||
|
std::condition_variable notify_;
|
||||||
|
stop_type stop_requested_{false};
|
||||||
|
|
||||||
|
public:
|
||||||
|
[[nodiscard]] auto expand(std::uint64_t size) -> api_error;
|
||||||
|
|
||||||
|
void initialize(app_config *cfg);
|
||||||
|
|
||||||
|
[[nodiscard]] static auto instance() -> cache_size_mgr & { return instance_; }
|
||||||
|
|
||||||
|
[[nodiscard]] auto shrink(std::uint64_t size) -> api_error;
|
||||||
|
|
||||||
|
[[nodiscard]] auto size() const -> std::uint64_t;
|
||||||
|
|
||||||
|
void stop();
|
||||||
|
};
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
|
#endif // REPERTORY_INCLUDE_FILE_MANAGER_CACHE_SIZE_MGR_HPP_
|
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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_DIRECT_OPEN_FILE_HPP_
|
||||||
|
#define REPERTORY_INCLUDE_FILE_MANAGER_DIRECT_OPEN_FILE_HPP_
|
||||||
|
|
||||||
|
#include "file_manager/ring_buffer_base.hpp"
|
||||||
|
|
||||||
|
#include "types/repertory.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
class i_provider;
|
||||||
|
class i_upload_manager;
|
||||||
|
|
||||||
|
class direct_open_file final : public ring_buffer_base {
|
||||||
|
public:
|
||||||
|
direct_open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||||
|
filesystem_item fsi, i_provider &provider);
|
||||||
|
|
||||||
|
~direct_open_file() override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
direct_open_file() = delete;
|
||||||
|
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;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::array<data_buffer, min_ring_size> ring_data_;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
[[nodiscard]] auto on_check_start() -> bool 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 use_buffer(std::size_t chunk,
|
||||||
|
std::function<api_error(data_buffer &)> func)
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
[[nodiscard]] auto native_operation(native_operation_callback /* callback */)
|
||||||
|
-> api_error override {
|
||||||
|
return api_error::not_supported;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto native_operation(std::uint64_t /* new_file_size */,
|
||||||
|
native_operation_callback /* callback */)
|
||||||
|
-> api_error override {
|
||||||
|
return api_error::not_supported;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
|
#endif // REPERTORY_INCLUDE_FILE_MANAGER_DIRECT_OPEN_FILE_HPP_
|
@ -32,23 +32,6 @@ E_SIMPLE2(download_begin, info, true,
|
|||||||
std::string, dest_path, dest, E_FROM_STRING
|
std::string, dest_path, dest, E_FROM_STRING
|
||||||
);
|
);
|
||||||
|
|
||||||
E_SIMPLE5(download_chunk_begin, debug, true,
|
|
||||||
std::string, api_path, ap, E_FROM_STRING,
|
|
||||||
std::string, dest_path, dest, E_FROM_STRING,
|
|
||||||
std::size_t, chunk, chunk, E_FROM_SIZE_T,
|
|
||||||
std::size_t, total, total, E_FROM_SIZE_T,
|
|
||||||
std::size_t, complete, complete, E_FROM_SIZE_T
|
|
||||||
);
|
|
||||||
|
|
||||||
E_SIMPLE6(download_chunk_end, debug, true,
|
|
||||||
std::string, api_path, ap, E_FROM_STRING,
|
|
||||||
std::string, dest_path, dest, E_FROM_STRING,
|
|
||||||
std::size_t, chunk, chunk, E_FROM_SIZE_T,
|
|
||||||
std::size_t, total, total, E_FROM_SIZE_T,
|
|
||||||
std::size_t, complete, complete, E_FROM_SIZE_T,
|
|
||||||
api_error, result, result, E_FROM_API_FILE_ERROR
|
|
||||||
);
|
|
||||||
|
|
||||||
E_SIMPLE3(download_end, info, true,
|
E_SIMPLE3(download_end, info, true,
|
||||||
std::string, api_path, ap, E_FROM_STRING,
|
std::string, api_path, ap, E_FROM_STRING,
|
||||||
std::string, dest_path, dest, E_FROM_STRING,
|
std::string, dest_path, dest, E_FROM_STRING,
|
||||||
@ -78,19 +61,25 @@ E_SIMPLE3(download_resume_add_failed, error, true,
|
|||||||
std::string, error, err, E_FROM_STRING
|
std::string, error, err, E_FROM_STRING
|
||||||
);
|
);
|
||||||
|
|
||||||
E_SIMPLE2(download_resume_added, info, true,
|
E_SIMPLE2(download_resume_added, debug, true,
|
||||||
std::string, api_path, ap, E_FROM_STRING,
|
std::string, api_path, ap, E_FROM_STRING,
|
||||||
std::string, dest_path, dest, E_FROM_STRING
|
std::string, dest_path, dest, E_FROM_STRING
|
||||||
);
|
);
|
||||||
|
|
||||||
E_SIMPLE2(download_resume_removed, info, true,
|
E_SIMPLE2(download_resume_removed, debug, true,
|
||||||
std::string, api_path, ap, E_FROM_STRING,
|
std::string, api_path, ap, E_FROM_STRING,
|
||||||
std::string, dest_path, dest, E_FROM_STRING
|
std::string, dest_path, dest, E_FROM_STRING
|
||||||
);
|
);
|
||||||
|
|
||||||
E_SIMPLE1(item_timeout, debug, true,
|
E_SIMPLE1(item_timeout, trace, true,
|
||||||
std::string, api_path, ap, E_FROM_STRING
|
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
|
// clang-format on
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
|
||||||
|
@ -22,15 +22,14 @@
|
|||||||
#ifndef REPERTORY_INCLUDE_FILE_MANAGER_FILE_MANAGER_HPP_
|
#ifndef REPERTORY_INCLUDE_FILE_MANAGER_FILE_MANAGER_HPP_
|
||||||
#define REPERTORY_INCLUDE_FILE_MANAGER_FILE_MANAGER_HPP_
|
#define REPERTORY_INCLUDE_FILE_MANAGER_FILE_MANAGER_HPP_
|
||||||
|
|
||||||
|
#include "db/i_file_mgr_db.hpp"
|
||||||
#include "events/event_system.hpp"
|
#include "events/event_system.hpp"
|
||||||
#include "events/events.hpp"
|
#include "events/events.hpp"
|
||||||
#include "file_manager/i_file_manager.hpp"
|
#include "file_manager/i_file_manager.hpp"
|
||||||
#include "file_manager/i_open_file.hpp"
|
#include "file_manager/i_open_file.hpp"
|
||||||
#include "file_manager/i_upload_manager.hpp"
|
#include "file_manager/i_upload_manager.hpp"
|
||||||
#include "file_manager/upload.hpp"
|
#include "file_manager/upload.hpp"
|
||||||
#include "platform/platform.hpp"
|
|
||||||
#include "types/repertory.hpp"
|
#include "types/repertory.hpp"
|
||||||
#include "utils/db/sqlite/db_common.hpp"
|
|
||||||
#include "utils/file.hpp"
|
#include "utils/file.hpp"
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
@ -57,7 +56,7 @@ private:
|
|||||||
i_provider &provider_;
|
i_provider &provider_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
utils::db::sqlite::db3_t db_;
|
std::unique_ptr<i_file_mgr_db> mgr_db_;
|
||||||
std::atomic<std::uint64_t> next_handle_{0U};
|
std::atomic<std::uint64_t> next_handle_{0U};
|
||||||
mutable std::recursive_mutex open_file_mtx_;
|
mutable std::recursive_mutex open_file_mtx_;
|
||||||
std::unordered_map<std::string, std::shared_ptr<i_closeable_open_file>>
|
std::unordered_map<std::string, std::shared_ptr<i_closeable_open_file>>
|
||||||
@ -69,6 +68,8 @@ private:
|
|||||||
std::unique_ptr<std::thread> upload_thread_;
|
std::unique_ptr<std::thread> upload_thread_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
[[nodiscard]] auto close_all(const std::string &api_path) -> bool;
|
||||||
|
|
||||||
void close_timed_out_files();
|
void close_timed_out_files();
|
||||||
|
|
||||||
auto get_open_file_by_handle(std::uint64_t handle) const
|
auto get_open_file_by_handle(std::uint64_t handle) const
|
||||||
@ -84,6 +85,9 @@ private:
|
|||||||
void queue_upload(const std::string &api_path, const std::string &source_path,
|
void queue_upload(const std::string &api_path, const std::string &source_path,
|
||||||
bool no_lock);
|
bool no_lock);
|
||||||
|
|
||||||
|
void remove_resume(const std::string &api_path,
|
||||||
|
const std::string &source_path, bool no_lock);
|
||||||
|
|
||||||
void remove_upload(const std::string &api_path, bool no_lock);
|
void remove_upload(const std::string &api_path, bool no_lock);
|
||||||
|
|
||||||
void swap_renamed_items(std::string from_api_path, std::string to_api_path,
|
void swap_renamed_items(std::string from_api_path, std::string to_api_path,
|
||||||
@ -104,6 +108,11 @@ public:
|
|||||||
void remove_resume(const std::string &api_path,
|
void remove_resume(const std::string &api_path,
|
||||||
const std::string &source_path) override;
|
const std::string &source_path) override;
|
||||||
|
|
||||||
|
static auto remove_source_and_shrink_cache(const std::string &api_path,
|
||||||
|
const std::string &source_path,
|
||||||
|
std::uint64_t file_size,
|
||||||
|
bool allocated) -> bool;
|
||||||
|
|
||||||
void remove_upload(const std::string &api_path) override;
|
void remove_upload(const std::string &api_path) override;
|
||||||
|
|
||||||
void store_resume(const i_open_file &file) override;
|
void store_resume(const i_open_file &file) override;
|
||||||
@ -111,8 +120,6 @@ public:
|
|||||||
public:
|
public:
|
||||||
void close(std::uint64_t handle);
|
void close(std::uint64_t handle);
|
||||||
|
|
||||||
void close_all(const std::string &api_path);
|
|
||||||
|
|
||||||
[[nodiscard]] auto create(const std::string &api_path, api_meta_map &meta,
|
[[nodiscard]] auto create(const std::string &api_path, api_meta_map &meta,
|
||||||
open_file_data ofd, std::uint64_t &handle,
|
open_file_data ofd, std::uint64_t &handle,
|
||||||
std::shared_ptr<i_open_file> &file) -> api_error;
|
std::shared_ptr<i_open_file> &file) -> api_error;
|
||||||
@ -132,12 +139,13 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] auto get_open_handle_count() const -> std::size_t;
|
[[nodiscard]] auto get_open_handle_count() const -> std::size_t;
|
||||||
|
|
||||||
[[nodiscard]] auto get_stored_downloads() const -> std::vector<json>;
|
[[nodiscard]] auto get_stored_downloads() const
|
||||||
|
-> std::vector<i_file_mgr_db::resume_entry>;
|
||||||
|
|
||||||
[[nodiscard]] auto has_no_open_file_handles() const -> bool override;
|
[[nodiscard]] auto has_no_open_file_handles() const -> bool override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto is_processing(const std::string &api_path) const
|
||||||
is_processing(const std::string &api_path) const -> bool override;
|
-> bool override;
|
||||||
|
|
||||||
#if defined(PROJECT_TESTING)
|
#if defined(PROJECT_TESTING)
|
||||||
[[nodiscard]] auto open(std::shared_ptr<i_closeable_open_file> of,
|
[[nodiscard]] auto open(std::shared_ptr<i_closeable_open_file> of,
|
||||||
@ -150,19 +158,17 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] auto remove_file(const std::string &api_path) -> api_error;
|
[[nodiscard]] auto remove_file(const std::string &api_path) -> api_error;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto rename_directory(const std::string &from_api_path,
|
||||||
rename_directory(const std::string &from_api_path,
|
const std::string &to_api_path)
|
||||||
const std::string &to_api_path) -> api_error;
|
-> api_error;
|
||||||
|
|
||||||
[[nodiscard]] auto rename_file(const std::string &from_api_path,
|
[[nodiscard]] auto rename_file(const std::string &from_api_path,
|
||||||
const std::string &to_api_path,
|
const std::string &to_api_path, bool overwrite)
|
||||||
bool overwrite) -> api_error;
|
-> api_error;
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
|
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
void update_used_space(std::uint64_t &used_space) const override;
|
|
||||||
};
|
};
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
|
||||||
|
@ -31,21 +31,20 @@ class i_file_manager {
|
|||||||
INTERFACE_SETUP(i_file_manager);
|
INTERFACE_SETUP(i_file_manager);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto evict_file(const std::string &api_path)
|
||||||
evict_file(const std::string &api_path) -> bool = 0;
|
-> bool = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto get_directory_items(
|
|
||||||
const std::string &api_path) const -> directory_item_list = 0;
|
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto
|
||||||
get_open_files() const -> std::unordered_map<std::string, std::size_t> = 0;
|
get_directory_items(const std::string &api_path) const
|
||||||
|
-> directory_item_list = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_open_files() const
|
||||||
|
-> std::unordered_map<std::string, std::size_t> = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto has_no_open_file_handles() const -> bool = 0;
|
[[nodiscard]] virtual auto has_no_open_file_handles() const -> bool = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto is_processing(const std::string &api_path) const
|
||||||
is_processing(const std::string &api_path) const -> bool = 0;
|
-> bool = 0;
|
||||||
|
|
||||||
virtual void update_used_space(std::uint64_t &used_space) const = 0;
|
|
||||||
};
|
};
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
|
||||||
|
@ -40,30 +40,34 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] virtual auto get_filesystem_item() const -> filesystem_item = 0;
|
[[nodiscard]] virtual auto get_filesystem_item() const -> filesystem_item = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto get_open_data()
|
||||||
get_open_data() -> std::map<std::uint64_t, open_file_data> & = 0;
|
-> std::map<std::uint64_t, open_file_data> & = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto get_open_data() const
|
||||||
get_open_data() const -> const std::map<std::uint64_t, open_file_data> & = 0;
|
-> const std::map<std::uint64_t, open_file_data> & = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto get_open_data(std::uint64_t handle)
|
||||||
get_open_data(std::uint64_t handle) -> open_file_data & = 0;
|
-> open_file_data & = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto get_open_data(std::uint64_t handle) const
|
||||||
get_open_data(std::uint64_t handle) const -> const open_file_data & = 0;
|
-> const open_file_data & = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto get_open_file_count() const -> std::size_t = 0;
|
[[nodiscard]] virtual auto get_open_file_count() const -> std::size_t = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto get_read_state() const
|
||||||
get_read_state() const -> boost::dynamic_bitset<> = 0;
|
-> boost::dynamic_bitset<> = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto get_read_state(std::size_t chunk) const
|
||||||
get_read_state(std::size_t chunk) const -> bool = 0;
|
-> bool = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto get_source_path() const -> std::string = 0;
|
[[nodiscard]] virtual auto get_source_path() const -> std::string = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto is_complete() const -> bool = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto is_directory() const -> bool = 0;
|
[[nodiscard]] virtual auto is_directory() const -> bool = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto is_write_supported() const -> bool = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto has_handle(std::uint64_t handle) const -> bool = 0;
|
[[nodiscard]] virtual auto has_handle(std::uint64_t handle) const -> bool = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto
|
||||||
@ -74,11 +78,11 @@ public:
|
|||||||
native_operation_callback callback) -> api_error = 0;
|
native_operation_callback callback) -> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto read(std::size_t read_size,
|
[[nodiscard]] virtual auto read(std::size_t read_size,
|
||||||
std::uint64_t read_offset,
|
std::uint64_t read_offset, data_buffer &data)
|
||||||
data_buffer &data) -> api_error = 0;
|
-> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto resize(std::uint64_t new_file_size)
|
||||||
resize(std::uint64_t new_file_size) -> api_error = 0;
|
-> api_error = 0;
|
||||||
|
|
||||||
virtual void set_api_path(const std::string &api_path) = 0;
|
virtual void set_api_path(const std::string &api_path) = 0;
|
||||||
|
|
||||||
@ -93,20 +97,20 @@ class i_closeable_open_file : public i_open_file {
|
|||||||
public:
|
public:
|
||||||
virtual void add(std::uint64_t handle, open_file_data ofd) = 0;
|
virtual void add(std::uint64_t handle, open_file_data ofd) = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_allocated() const -> bool = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto can_close() const -> bool = 0;
|
[[nodiscard]] virtual auto can_close() const -> bool = 0;
|
||||||
|
|
||||||
virtual auto close() -> bool = 0;
|
virtual auto close() -> bool = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto get_handles() const
|
||||||
get_handles() const -> std::vector<std::uint64_t> = 0;
|
-> std::vector<std::uint64_t> = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto is_complete() const -> bool = 0;
|
|
||||||
|
|
||||||
[[nodiscard]] virtual auto is_modified() const -> bool = 0;
|
[[nodiscard]] virtual auto is_modified() const -> bool = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto is_write_supported() const -> bool = 0;
|
|
||||||
|
|
||||||
virtual void remove(std::uint64_t handle) = 0;
|
virtual void remove(std::uint64_t handle) = 0;
|
||||||
|
|
||||||
|
virtual void remove_all() = 0;
|
||||||
};
|
};
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
|
||||||
|
@ -29,14 +29,14 @@ class i_upload_manager {
|
|||||||
INTERFACE_SETUP(i_upload_manager);
|
INTERFACE_SETUP(i_upload_manager);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void queue_upload(const i_open_file &o) = 0;
|
virtual void queue_upload(const i_open_file &file) = 0;
|
||||||
|
|
||||||
virtual void remove_resume(const std::string &api_path,
|
virtual void remove_resume(const std::string &api_path,
|
||||||
const std::string &source_path) = 0;
|
const std::string &source_path) = 0;
|
||||||
|
|
||||||
virtual void remove_upload(const std::string &api_path) = 0;
|
virtual void remove_upload(const std::string &api_path) = 0;
|
||||||
|
|
||||||
virtual void store_resume(const i_open_file &o) = 0;
|
virtual void store_resume(const i_open_file &file) = 0;
|
||||||
};
|
};
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "file_manager/open_file_base.hpp"
|
#include "file_manager/open_file_base.hpp"
|
||||||
|
|
||||||
#include "types/repertory.hpp"
|
#include "types/repertory.hpp"
|
||||||
|
#include "utils/types/file/i_file.hpp"
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
class i_provider;
|
class i_provider;
|
||||||
@ -67,48 +68,60 @@ private:
|
|||||||
i_upload_manager &mgr_;
|
i_upload_manager &mgr_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool notified_ = false;
|
bool allocated{false};
|
||||||
std::size_t read_chunk_index_{};
|
std::unique_ptr<utils::file::i_file> nf_;
|
||||||
|
bool notified_{false};
|
||||||
|
std::size_t read_chunk_{};
|
||||||
boost::dynamic_bitset<> read_state_;
|
boost::dynamic_bitset<> read_state_;
|
||||||
std::unique_ptr<std::thread> reader_thread_;
|
std::unique_ptr<std::thread> reader_thread_;
|
||||||
std::unique_ptr<std::thread> download_thread_;
|
mutable std::recursive_mutex rw_mtx_;
|
||||||
stop_type stop_requested_ = false;
|
stop_type stop_requested_{false};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
[[nodiscard]] auto adjust_cache_size(std::uint64_t file_size,
|
||||||
|
bool shrink) -> api_error;
|
||||||
|
|
||||||
|
[[nodiscard]] auto check_start() -> api_error;
|
||||||
|
|
||||||
void download_chunk(std::size_t chunk, bool skip_active, bool should_reset);
|
void download_chunk(std::size_t chunk, bool skip_active, bool should_reset);
|
||||||
|
|
||||||
void download_range(std::size_t start_chunk_index,
|
void download_range(std::size_t begin_chunk, std::size_t end_chunk,
|
||||||
std::size_t end_chunk_index_inclusive, bool should_reset);
|
bool should_reset);
|
||||||
|
|
||||||
void set_modified();
|
void set_modified();
|
||||||
|
|
||||||
void update_background_reader(std::size_t read_chunk);
|
void set_read_state(std::size_t chunk);
|
||||||
|
|
||||||
protected:
|
void set_read_state(boost::dynamic_bitset<> read_state);
|
||||||
auto is_download_complete() const -> bool override {
|
|
||||||
return read_state_.all();
|
void update_reader(std::size_t chunk);
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
auto close() -> bool override;
|
auto close() -> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_allocated() const -> bool override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_read_state() const -> boost::dynamic_bitset<> override;
|
[[nodiscard]] auto get_read_state() const -> boost::dynamic_bitset<> override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_read_state(std::size_t chunk) const -> bool override;
|
[[nodiscard]] auto get_read_state(std::size_t chunk) const -> bool override;
|
||||||
|
|
||||||
[[nodiscard]] auto is_complete() const -> bool override;
|
[[nodiscard]] auto is_complete() const -> bool override;
|
||||||
|
|
||||||
auto is_write_supported() const -> bool override { return true; }
|
[[nodiscard]] auto is_write_supported() const -> bool override {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto native_operation(native_operation_callback callback)
|
[[nodiscard]] auto
|
||||||
-> api_error override;
|
native_operation(native_operation_callback callback) -> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto native_operation(std::uint64_t new_file_size,
|
[[nodiscard]] auto
|
||||||
native_operation_callback callback)
|
native_operation(std::uint64_t new_file_size,
|
||||||
-> api_error override;
|
native_operation_callback callback) -> api_error override;
|
||||||
|
|
||||||
void remove(std::uint64_t handle) override;
|
void remove(std::uint64_t handle) override;
|
||||||
|
|
||||||
|
void remove_all() override;
|
||||||
|
|
||||||
[[nodiscard]] auto read(std::size_t read_size, std::uint64_t read_offset,
|
[[nodiscard]] auto read(std::size_t read_size, std::uint64_t read_offset,
|
||||||
data_buffer &data) -> api_error override;
|
data_buffer &data) -> api_error override;
|
||||||
|
|
||||||
|
@ -24,20 +24,18 @@
|
|||||||
|
|
||||||
#include "file_manager/i_open_file.hpp"
|
#include "file_manager/i_open_file.hpp"
|
||||||
|
|
||||||
#include "utils/types/file/i_file.hpp"
|
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
class i_provider;
|
class i_provider;
|
||||||
|
|
||||||
class open_file_base : public i_closeable_open_file {
|
class open_file_base : public i_closeable_open_file {
|
||||||
public:
|
public:
|
||||||
open_file_base(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
open_file_base(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||||
filesystem_item fsi, i_provider &provider);
|
filesystem_item fsi, i_provider &provider, bool disable_io);
|
||||||
|
|
||||||
open_file_base(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
open_file_base(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||||
filesystem_item fsi,
|
filesystem_item fsi,
|
||||||
std::map<std::uint64_t, open_file_data> open_data,
|
std::map<std::uint64_t, open_file_data> open_data,
|
||||||
i_provider &provider);
|
i_provider &provider, bool disable_io);
|
||||||
|
|
||||||
~open_file_base() override = default;
|
~open_file_base() override = default;
|
||||||
|
|
||||||
@ -98,7 +96,7 @@ public:
|
|||||||
[[nodiscard]] auto get_result() -> api_error;
|
[[nodiscard]] auto get_result() -> api_error;
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
std::uint64_t chunk_size_;
|
std::uint64_t chunk_size_;
|
||||||
std::uint8_t chunk_timeout_;
|
std::uint8_t chunk_timeout_;
|
||||||
filesystem_item fsi_;
|
filesystem_item fsi_;
|
||||||
@ -107,21 +105,19 @@ protected:
|
|||||||
i_provider &provider_;
|
i_provider &provider_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::unordered_map<std::size_t, std::shared_ptr<download>> active_downloads_;
|
||||||
api_error error_{api_error::success};
|
api_error error_{api_error::success};
|
||||||
mutable std::mutex error_mtx_;
|
mutable std::mutex error_mtx_;
|
||||||
|
mutable std::recursive_mutex file_mtx_;
|
||||||
stop_type io_stop_requested_{false};
|
stop_type io_stop_requested_{false};
|
||||||
std::unique_ptr<std::thread> io_thread_;
|
std::unique_ptr<std::thread> io_thread_;
|
||||||
|
|
||||||
protected:
|
|
||||||
std::unordered_map<std::size_t, std::shared_ptr<download>> active_downloads_;
|
|
||||||
mutable std::recursive_mutex file_mtx_;
|
|
||||||
std::atomic<std::chrono::system_clock::time_point> last_access_{
|
|
||||||
std::chrono::system_clock::now()};
|
|
||||||
bool modified_{false};
|
|
||||||
std::unique_ptr<utils::file::i_file> nf_;
|
|
||||||
mutable std::mutex io_thread_mtx_;
|
mutable std::mutex io_thread_mtx_;
|
||||||
std::condition_variable io_thread_notify_;
|
std::condition_variable io_thread_notify_;
|
||||||
std::deque<std::shared_ptr<io_item>> io_thread_queue_;
|
std::deque<std::shared_ptr<io_item>> io_thread_queue_;
|
||||||
|
std::atomic<std::chrono::system_clock::time_point> last_access_{
|
||||||
|
std::chrono::system_clock::now(),
|
||||||
|
};
|
||||||
|
bool modified_{false};
|
||||||
bool removed_{false};
|
bool removed_{false};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -130,11 +126,42 @@ private:
|
|||||||
protected:
|
protected:
|
||||||
[[nodiscard]] auto do_io(std::function<api_error()> action) -> api_error;
|
[[nodiscard]] auto do_io(std::function<api_error()> action) -> api_error;
|
||||||
|
|
||||||
virtual auto is_download_complete() const -> bool = 0;
|
[[nodiscard]] auto get_active_downloads()
|
||||||
|
-> std::unordered_map<std::size_t, std::shared_ptr<download>> & {
|
||||||
|
return active_downloads_;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_mutex() const -> std::recursive_mutex & {
|
||||||
|
return file_mtx_;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_last_chunk_size() const -> std::size_t;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_provider() -> i_provider & { return provider_; }
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_provider() const -> const i_provider & {
|
||||||
|
return provider_;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto is_removed() const -> bool;
|
||||||
|
|
||||||
|
void notify_io();
|
||||||
|
|
||||||
void reset_timeout();
|
void reset_timeout();
|
||||||
|
|
||||||
auto set_api_error(const api_error &e) -> api_error;
|
auto set_api_error(const api_error &err) -> api_error;
|
||||||
|
|
||||||
|
void set_file_size(std::uint64_t size);
|
||||||
|
|
||||||
|
void set_last_chunk_size(std::size_t size);
|
||||||
|
|
||||||
|
void set_modified(bool modified);
|
||||||
|
|
||||||
|
void set_removed(bool removed);
|
||||||
|
|
||||||
|
void set_source_path(std::string source_path);
|
||||||
|
|
||||||
|
void wait_for_io(stop_type &stop_requested);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void add(std::uint64_t handle, open_file_data ofd) override;
|
void add(std::uint64_t handle, open_file_data ofd) override;
|
||||||
@ -143,6 +170,8 @@ public:
|
|||||||
|
|
||||||
auto close() -> bool override;
|
auto close() -> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_allocated() const -> bool override { return false; }
|
||||||
|
|
||||||
[[nodiscard]] auto get_api_error() const -> api_error;
|
[[nodiscard]] auto get_api_error() const -> api_error;
|
||||||
|
|
||||||
[[nodiscard]] auto get_api_path() const -> std::string override;
|
[[nodiscard]] auto get_api_path() const -> std::string override;
|
||||||
@ -157,27 +186,23 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] auto get_handles() const -> std::vector<std::uint64_t> override;
|
[[nodiscard]] auto get_handles() const -> std::vector<std::uint64_t> override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_open_data()
|
[[nodiscard]] auto
|
||||||
-> std::map<std::uint64_t, open_file_data> & override;
|
get_open_data() -> std::map<std::uint64_t, open_file_data> & override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_open_data() const
|
[[nodiscard]] auto get_open_data() const
|
||||||
-> const std::map<std::uint64_t, open_file_data> & override;
|
-> const std::map<std::uint64_t, open_file_data> & override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_open_data(std::uint64_t handle)
|
[[nodiscard]] auto
|
||||||
-> open_file_data & override;
|
get_open_data(std::uint64_t handle) -> open_file_data & override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_open_data(std::uint64_t handle) const
|
[[nodiscard]] auto
|
||||||
-> const open_file_data & override;
|
get_open_data(std::uint64_t handle) const -> const open_file_data & override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_open_file_count() const -> std::size_t override;
|
[[nodiscard]] auto get_open_file_count() const -> std::size_t override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_source_path() const -> std::string override {
|
[[nodiscard]] auto get_source_path() const -> std::string override;
|
||||||
return fsi_.source_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto has_handle(std::uint64_t handle) const -> bool override {
|
[[nodiscard]] auto has_handle(std::uint64_t handle) const -> bool override;
|
||||||
return open_data_.find(handle) != open_data_.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto is_directory() const -> bool override {
|
[[nodiscard]] auto is_directory() const -> bool override {
|
||||||
return fsi_.directory;
|
return fsi_.directory;
|
||||||
@ -187,6 +212,8 @@ public:
|
|||||||
|
|
||||||
void remove(std::uint64_t handle) override;
|
void remove(std::uint64_t handle) override;
|
||||||
|
|
||||||
|
void remove_all() override;
|
||||||
|
|
||||||
void set_api_path(const std::string &api_path) override;
|
void set_api_path(const std::string &api_path) override;
|
||||||
};
|
};
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
150
repertory/librepertory/include/file_manager/ring_buffer_base.hpp
Normal file
150
repertory/librepertory/include/file_manager/ring_buffer_base.hpp
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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_RING_BUFFER_BASE_HPP_
|
||||||
|
#define REPERTORY_INCLUDE_FILE_MANAGER_RING_BUFFER_BASE_HPP_
|
||||||
|
|
||||||
|
#include "file_manager/open_file_base.hpp"
|
||||||
|
|
||||||
|
#include "types/repertory.hpp"
|
||||||
|
#include "utils/file.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
class i_provider;
|
||||||
|
class i_upload_manager;
|
||||||
|
|
||||||
|
class ring_buffer_base : public open_file_base {
|
||||||
|
public:
|
||||||
|
ring_buffer_base(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||||
|
filesystem_item fsi, i_provider &provider,
|
||||||
|
std::size_t ring_size, bool disable_io);
|
||||||
|
|
||||||
|
~ring_buffer_base() override = default;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ring_buffer_base() = delete;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr const auto min_ring_size{5U};
|
||||||
|
|
||||||
|
private:
|
||||||
|
boost::dynamic_bitset<> read_state_;
|
||||||
|
std::size_t total_chunks_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::condition_variable chunk_notify_;
|
||||||
|
mutable std::mutex chunk_mtx_;
|
||||||
|
std::mutex read_mtx_;
|
||||||
|
std::unique_ptr<std::thread> reader_thread_;
|
||||||
|
std::size_t ring_begin_{};
|
||||||
|
std::size_t ring_end_{};
|
||||||
|
std::size_t ring_pos_{};
|
||||||
|
stop_type stop_requested_{false};
|
||||||
|
|
||||||
|
private:
|
||||||
|
[[nodiscard]] auto check_start() -> api_error;
|
||||||
|
|
||||||
|
auto download_chunk(std::size_t chunk, bool skip_active) -> api_error;
|
||||||
|
|
||||||
|
void reader_thread();
|
||||||
|
|
||||||
|
void update_position(std::size_t count, bool is_forward);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
[[nodiscard]] auto has_reader_thread() const -> bool {
|
||||||
|
return reader_thread_ != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_ring_size() const -> std::size_t {
|
||||||
|
return read_state_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[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_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 = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto
|
||||||
|
use_buffer(std::size_t chunk,
|
||||||
|
std::function<api_error(data_buffer &)> func) -> api_error = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
auto close() -> bool override;
|
||||||
|
|
||||||
|
void forward(std::size_t count);
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_current_chunk() const -> std::size_t {
|
||||||
|
return ring_pos_;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_first_chunk() const -> std::size_t {
|
||||||
|
return ring_begin_;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_last_chunk() const -> std::size_t { return ring_end_; }
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_read_state() const -> boost::dynamic_bitset<> override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_read_state(std::size_t chunk) const -> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_total_chunks() const -> std::size_t {
|
||||||
|
return total_chunks_;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto is_complete() const -> bool override { return false; }
|
||||||
|
|
||||||
|
[[nodiscard]] auto is_write_supported() const -> bool override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto read(std::size_t read_size, std::uint64_t read_offset,
|
||||||
|
data_buffer &data) -> api_error override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto resize(std::uint64_t /* size */) -> api_error override {
|
||||||
|
return api_error::not_supported;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reverse(std::size_t count);
|
||||||
|
|
||||||
|
void set(std::size_t first_chunk, std::size_t current_chunk);
|
||||||
|
|
||||||
|
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 {
|
||||||
|
return api_error::not_supported;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
|
#endif // REPERTORY_INCLUDE_FILE_MANAGER_RING_BUFFER_BASE_HPP_
|
@ -22,20 +22,17 @@
|
|||||||
#ifndef REPERTORY_INCLUDE_FILE_MANAGER_RING_BUFFER_OPEN_FILE_HPP_
|
#ifndef REPERTORY_INCLUDE_FILE_MANAGER_RING_BUFFER_OPEN_FILE_HPP_
|
||||||
#define REPERTORY_INCLUDE_FILE_MANAGER_RING_BUFFER_OPEN_FILE_HPP_
|
#define REPERTORY_INCLUDE_FILE_MANAGER_RING_BUFFER_OPEN_FILE_HPP_
|
||||||
|
|
||||||
#include "file_manager/open_file_base.hpp"
|
#include "file_manager/ring_buffer_base.hpp"
|
||||||
|
|
||||||
#include "types/repertory.hpp"
|
#include "types/repertory.hpp"
|
||||||
|
#include "utils/file.hpp"
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
class i_provider;
|
class i_provider;
|
||||||
class i_upload_manager;
|
class i_upload_manager;
|
||||||
|
|
||||||
class ring_buffer_open_file final : public open_file_base {
|
class ring_buffer_open_file final : public ring_buffer_base {
|
||||||
public:
|
public:
|
||||||
ring_buffer_open_file(std::string buffer_directory, std::uint64_t chunk_size,
|
|
||||||
std::uint8_t chunk_timeout, filesystem_item fsi,
|
|
||||||
i_provider &provider);
|
|
||||||
|
|
||||||
ring_buffer_open_file(std::string buffer_directory, std::uint64_t chunk_size,
|
ring_buffer_open_file(std::string buffer_directory, std::uint64_t chunk_size,
|
||||||
std::uint8_t chunk_timeout, filesystem_item fsi,
|
std::uint8_t chunk_timeout, filesystem_item fsi,
|
||||||
i_provider &provider, std::size_t ring_size);
|
i_provider &provider, std::size_t ring_size);
|
||||||
@ -46,85 +43,49 @@ public:
|
|||||||
ring_buffer_open_file() = delete;
|
ring_buffer_open_file() = delete;
|
||||||
ring_buffer_open_file(const ring_buffer_open_file &) noexcept = delete;
|
ring_buffer_open_file(const ring_buffer_open_file &) noexcept = delete;
|
||||||
ring_buffer_open_file(ring_buffer_open_file &&) noexcept = delete;
|
ring_buffer_open_file(ring_buffer_open_file &&) noexcept = delete;
|
||||||
auto operator=(ring_buffer_open_file &&) noexcept
|
auto operator=(ring_buffer_open_file &&) noexcept -> ring_buffer_open_file & =
|
||||||
-> ring_buffer_open_file & = delete;
|
delete;
|
||||||
auto operator=(const ring_buffer_open_file &) noexcept
|
auto operator=(const ring_buffer_open_file &) noexcept
|
||||||
-> ring_buffer_open_file & = delete;
|
-> ring_buffer_open_file & = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::dynamic_bitset<> ring_state_;
|
std::string source_path_;
|
||||||
std::size_t total_chunks_;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<std::thread> chunk_forward_thread_;
|
std::unique_ptr<utils::file::i_file> nf_;
|
||||||
std::unique_ptr<std::thread> chunk_reverse_thread_;
|
|
||||||
std::condition_variable chunk_notify_;
|
|
||||||
mutable std::mutex chunk_mtx_;
|
|
||||||
std::size_t current_chunk_{};
|
|
||||||
std::size_t first_chunk_{};
|
|
||||||
std::size_t last_chunk_;
|
|
||||||
|
|
||||||
private:
|
|
||||||
auto download_chunk(std::size_t chunk) -> api_error;
|
|
||||||
|
|
||||||
void forward_reader_thread(std::size_t count);
|
|
||||||
|
|
||||||
void reverse_reader_thread(std::size_t count);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
auto is_download_complete() const -> bool override;
|
[[nodiscard]] auto on_check_start() -> bool override;
|
||||||
|
|
||||||
public:
|
[[nodiscard]] auto
|
||||||
void forward(std::size_t count);
|
on_chunk_downloaded(std::size_t chunk,
|
||||||
|
const data_buffer &buffer) -> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_current_chunk() const -> std::size_t {
|
[[nodiscard]] auto
|
||||||
return current_chunk_;
|
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 get_first_chunk() const -> std::size_t {
|
[[nodiscard]] auto use_buffer(std::size_t chunk,
|
||||||
return first_chunk_;
|
std::function<api_error(data_buffer &)> func)
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_last_chunk() const -> std::size_t {
|
|
||||||
return last_chunk_;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_read_state() const -> boost::dynamic_bitset<> override;
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_read_state(std::size_t chunk) const -> bool override;
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_total_chunks() const -> std::size_t {
|
|
||||||
return total_chunks_;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto is_complete() const -> bool override { return true; }
|
|
||||||
|
|
||||||
auto is_write_supported() const -> bool override { return false; }
|
|
||||||
|
|
||||||
[[nodiscard]] auto native_operation(native_operation_callback callback)
|
|
||||||
-> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto native_operation(std::uint64_t, native_operation_callback)
|
public:
|
||||||
|
[[nodiscard]] static auto can_handle_file(std::uint64_t file_size,
|
||||||
|
std::size_t chunk_size,
|
||||||
|
std::size_t ring_size) -> bool;
|
||||||
|
|
||||||
|
[[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 {
|
-> api_error override {
|
||||||
return api_error::not_supported;
|
return api_error::not_supported;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto read(std::size_t read_size, std::uint64_t read_offset,
|
[[nodiscard]] auto get_source_path() const -> std::string override {
|
||||||
data_buffer &data) -> api_error override;
|
return source_path_;
|
||||||
|
|
||||||
[[nodiscard]] auto resize(std::uint64_t) -> api_error override {
|
|
||||||
return api_error::not_supported;
|
|
||||||
}
|
|
||||||
|
|
||||||
void reverse(std::size_t count);
|
|
||||||
|
|
||||||
void set(std::size_t first_chunk, std::size_t current_chunk);
|
|
||||||
|
|
||||||
void set_api_path(const std::string &api_path) override;
|
|
||||||
|
|
||||||
[[nodiscard]] auto write(std::uint64_t, const data_buffer &, std::size_t &)
|
|
||||||
-> api_error override {
|
|
||||||
return api_error::not_supported;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
#ifndef REPERTORY_INCLUDE_PROVIDERS_BASE_PROVIDER_HPP_
|
#ifndef REPERTORY_INCLUDE_PROVIDERS_BASE_PROVIDER_HPP_
|
||||||
#define REPERTORY_INCLUDE_PROVIDERS_BASE_PROVIDER_HPP_
|
#define REPERTORY_INCLUDE_PROVIDERS_BASE_PROVIDER_HPP_
|
||||||
|
|
||||||
|
#include "db/i_meta_db.hpp"
|
||||||
#include "providers/i_provider.hpp"
|
#include "providers/i_provider.hpp"
|
||||||
#include "providers/meta_db.hpp"
|
|
||||||
#include "types/repertory.hpp"
|
#include "types/repertory.hpp"
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
@ -32,6 +32,13 @@ class i_file_manager;
|
|||||||
class i_http_comm;
|
class i_http_comm;
|
||||||
|
|
||||||
class base_provider : public i_provider {
|
class base_provider : public i_provider {
|
||||||
|
private:
|
||||||
|
struct removed_item final {
|
||||||
|
std::string api_path;
|
||||||
|
bool directory{};
|
||||||
|
std::string source_path;
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
base_provider(app_config &config, i_http_comm &comm)
|
base_provider(app_config &config, i_http_comm &comm)
|
||||||
: config_(config), comm_(comm) {}
|
: config_(config), comm_(comm) {}
|
||||||
@ -42,24 +49,37 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
api_item_added_callback api_item_added_;
|
api_item_added_callback api_item_added_;
|
||||||
std::unique_ptr<meta_db> db3_;
|
std::unique_ptr<i_meta_db> db3_;
|
||||||
i_file_manager *fm_{};
|
i_file_manager *fm_{};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void remove_deleted_files(bool source_only);
|
void add_all_items(const stop_type &stop_requested);
|
||||||
|
|
||||||
|
void process_removed_directories(std::deque<removed_item> removed_list,
|
||||||
|
const stop_type &stop_requested);
|
||||||
|
|
||||||
|
void process_removed_files(std::deque<removed_item> removed_list,
|
||||||
|
const stop_type &stop_requested);
|
||||||
|
|
||||||
|
void process_removed_items(const stop_type &stop_requested);
|
||||||
|
|
||||||
|
void remove_deleted_items(const stop_type &stop_requested);
|
||||||
|
|
||||||
|
void remove_unmatched_source_files(const stop_type &stop_requested);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
[[nodiscard]] static auto
|
[[nodiscard]] static auto create_api_file(std::string path, std::string key,
|
||||||
create_api_file(std::string path, std::string key, std::uint64_t size,
|
std::uint64_t size,
|
||||||
std::uint64_t file_time) -> api_file;
|
std::uint64_t file_time)
|
||||||
|
-> api_file;
|
||||||
|
|
||||||
[[nodiscard]] static auto create_api_file(std::string path,
|
[[nodiscard]] static auto create_api_file(std::string path,
|
||||||
std::uint64_t size,
|
std::uint64_t size,
|
||||||
api_meta_map &meta) -> api_file;
|
api_meta_map &meta) -> api_file;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto create_directory_impl(const std::string &api_path,
|
||||||
create_directory_impl(const std::string &api_path,
|
api_meta_map &meta)
|
||||||
api_meta_map &meta) -> api_error = 0;
|
-> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto
|
||||||
create_file_extra(const std::string & /* api_path */,
|
create_file_extra(const std::string & /* api_path */,
|
||||||
@ -71,12 +91,14 @@ protected:
|
|||||||
return api_item_added_;
|
return api_item_added_;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto get_api_item_added() const
|
||||||
get_api_item_added() const -> const api_item_added_callback & {
|
-> const api_item_added_callback & {
|
||||||
return api_item_added_;
|
return api_item_added_;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto get_comm() const -> i_http_comm & { return comm_; }
|
[[nodiscard]] auto get_comm() -> i_http_comm & { return comm_; }
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_comm() const -> const i_http_comm & { return comm_; }
|
||||||
|
|
||||||
[[nodiscard]] auto get_config() -> app_config & { return config_; }
|
[[nodiscard]] auto get_config() -> app_config & { return config_; }
|
||||||
|
|
||||||
@ -84,7 +106,9 @@ protected:
|
|||||||
return config_;
|
return config_;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto get_db() -> meta_db & { return *db3_; }
|
[[nodiscard]] auto get_db() -> i_meta_db & { return *db3_; }
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_db() const -> const i_meta_db & { return *db3_; }
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto
|
||||||
get_directory_items_impl(const std::string &api_path,
|
get_directory_items_impl(const std::string &api_path,
|
||||||
@ -96,23 +120,22 @@ protected:
|
|||||||
return fm_;
|
return fm_;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto remove_directory_impl(const std::string &api_path)
|
||||||
get_used_drive_space_impl() const -> std::uint64_t = 0;
|
-> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto remove_file_impl(const std::string &api_path)
|
||||||
remove_directory_impl(const std::string &api_path) -> api_error = 0;
|
-> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto upload_file_impl(const std::string &api_path,
|
||||||
remove_file_impl(const std::string &api_path) -> api_error = 0;
|
const std::string &source_path,
|
||||||
|
stop_type &stop_requested)
|
||||||
[[nodiscard]] virtual auto
|
-> api_error = 0;
|
||||||
upload_file_impl(const std::string &api_path, const std::string &source_path,
|
|
||||||
stop_type &stop_requested) -> api_error = 0;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] auto create_directory_clone_source_meta(
|
[[nodiscard]] auto
|
||||||
const std::string &source_api_path,
|
create_directory_clone_source_meta(const std::string &source_api_path,
|
||||||
const std::string &api_path) -> api_error override;
|
const std::string &api_path)
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto create_directory(const std::string &api_path,
|
[[nodiscard]] auto create_directory(const std::string &api_path,
|
||||||
api_meta_map &meta) -> api_error override;
|
api_meta_map &meta) -> api_error override;
|
||||||
@ -120,74 +143,82 @@ public:
|
|||||||
[[nodiscard]] auto create_file(const std::string &api_path,
|
[[nodiscard]] auto create_file(const std::string &api_path,
|
||||||
api_meta_map &meta) -> api_error override;
|
api_meta_map &meta) -> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto get_api_path_from_source(const std::string &source_path,
|
||||||
get_api_path_from_source(const std::string &source_path,
|
std::string &api_path) const
|
||||||
std::string &api_path) const -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_directory_items(const std::string &api_path,
|
||||||
|
directory_item_list &list) const
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_file_size(const std::string &api_path,
|
||||||
|
std::uint64_t &file_size) const
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_filesystem_item(const std::string &api_path,
|
||||||
|
bool directory,
|
||||||
|
filesystem_item &fsi) const
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_filesystem_item_and_file(const std::string &api_path,
|
||||||
|
api_file &f,
|
||||||
|
filesystem_item &fsi) const
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto
|
||||||
get_directory_items(const std::string &api_path,
|
get_filesystem_item_from_source_path(const std::string &source_path,
|
||||||
directory_item_list &list) const -> api_error override;
|
filesystem_item &fsi) const
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto get_item_meta(const std::string &api_path,
|
||||||
get_file_size(const std::string &api_path,
|
api_meta_map &meta) const
|
||||||
std::uint64_t &file_size) const -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto get_item_meta(const std::string &api_path,
|
||||||
get_filesystem_item(const std::string &api_path, bool directory,
|
const std::string &key,
|
||||||
filesystem_item &fsi) const -> api_error override;
|
std::string &value) const
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_filesystem_item_and_file(
|
[[nodiscard]] auto get_pinned_files() const
|
||||||
const std::string &api_path, api_file &f,
|
-> std::vector<std::string> override;
|
||||||
filesystem_item &fsi) const -> api_error override;
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_filesystem_item_from_source_path(
|
|
||||||
const std::string &source_path,
|
|
||||||
filesystem_item &fsi) const -> api_error override;
|
|
||||||
|
|
||||||
[[nodiscard]] auto
|
|
||||||
get_item_meta(const std::string &api_path,
|
|
||||||
api_meta_map &meta) const -> api_error override;
|
|
||||||
|
|
||||||
[[nodiscard]] auto
|
|
||||||
get_item_meta(const std::string &api_path, const std::string &key,
|
|
||||||
std::string &value) const -> api_error override;
|
|
||||||
|
|
||||||
[[nodiscard]] auto
|
|
||||||
get_pinned_files() const -> std::vector<std::string> override;
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_total_item_count() const -> std::uint64_t override;
|
[[nodiscard]] auto get_total_item_count() const -> std::uint64_t override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_used_drive_space() const -> std::uint64_t override;
|
[[nodiscard]] auto get_used_drive_space() const -> std::uint64_t override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto is_file_writeable(const std::string &api_path) const
|
||||||
is_file_writeable(const std::string &api_path) const -> bool override;
|
-> bool override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto is_read_only() const -> bool override { return false; }
|
||||||
remove_directory(const std::string &api_path) -> api_error override;
|
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto remove_directory(const std::string &api_path)
|
||||||
remove_file(const std::string &api_path) -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto remove_file(const std::string &api_path)
|
||||||
remove_item_meta(const std::string &api_path,
|
-> api_error override;
|
||||||
const std::string &key) -> api_error override;
|
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto remove_item_meta(const std::string &api_path,
|
||||||
set_item_meta(const std::string &api_path, const std::string &key,
|
const std::string &key)
|
||||||
const std::string &value) -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto set_item_meta(const std::string &api_path,
|
||||||
set_item_meta(const std::string &api_path,
|
const std::string &key,
|
||||||
const api_meta_map &meta) -> api_error override;
|
const std::string &value)
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto set_item_meta(const std::string &api_path,
|
||||||
|
const api_meta_map &meta)
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto start(api_item_added_callback api_item_added,
|
[[nodiscard]] auto start(api_item_added_callback api_item_added,
|
||||||
i_file_manager *mgr) -> bool override;
|
i_file_manager *mgr) -> bool override;
|
||||||
|
|
||||||
void stop() override;
|
void stop() override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto upload_file(const std::string &api_path,
|
||||||
upload_file(const std::string &api_path, const std::string &source_path,
|
const std::string &source_path,
|
||||||
stop_type &stop_requested) -> api_error override;
|
stop_type &stop_requested)
|
||||||
|
-> api_error override;
|
||||||
};
|
};
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@
|
|||||||
#define REPERTORY_INCLUDE_PROVIDERS_ENCRYPT_ENCRYPT_PROVIDER_HPP_
|
#define REPERTORY_INCLUDE_PROVIDERS_ENCRYPT_ENCRYPT_PROVIDER_HPP_
|
||||||
|
|
||||||
#include "app_config.hpp"
|
#include "app_config.hpp"
|
||||||
|
#include "db/i_file_db.hpp"
|
||||||
#include "providers/i_provider.hpp"
|
#include "providers/i_provider.hpp"
|
||||||
#include "utils/db/sqlite/db_common.hpp"
|
|
||||||
#include "utils/encrypting_reader.hpp"
|
#include "utils/encrypting_reader.hpp"
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
@ -45,21 +45,22 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
struct reader_info final {
|
struct reader_info final {
|
||||||
std::chrono::system_clock::time_point last_access_time =
|
std::chrono::system_clock::time_point last_access_time{
|
||||||
std::chrono::system_clock::now();
|
std::chrono::system_clock::now(),
|
||||||
std::unique_ptr<utils::encryption::encrypting_reader> reader{};
|
};
|
||||||
|
std::unique_ptr<utils::encryption::encrypting_reader> reader;
|
||||||
std::mutex reader_mtx;
|
std::mutex reader_mtx;
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
app_config &config_;
|
app_config &config_;
|
||||||
utils::db::sqlite::db3_t db_;
|
encrypt_config encrypt_config_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
i_file_manager *fm_ = nullptr;
|
std::unique_ptr<i_file_db> db_{nullptr};
|
||||||
std::unordered_map<std::string, std::shared_ptr<reader_info>>
|
i_file_manager *fm_{nullptr};
|
||||||
reader_lookup_{};
|
std::unordered_map<std::string, std::shared_ptr<reader_info>> reader_lookup_;
|
||||||
std::recursive_mutex reader_lookup_mtx_{};
|
std::recursive_mutex reader_lookup_mtx_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static auto create_api_file(const std::string &api_path, bool directory,
|
static auto create_api_file(const std::string &api_path, bool directory,
|
||||||
@ -73,71 +74,82 @@ private:
|
|||||||
const std::string &source_path)>
|
const std::string &source_path)>
|
||||||
callback) const -> api_error;
|
callback) const -> api_error;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_encrypt_config() const -> const encrypt_config & {
|
||||||
|
return encrypt_config_;
|
||||||
|
}
|
||||||
|
|
||||||
auto process_directory_entry(const utils::file::i_fs_item &dir_entry,
|
auto process_directory_entry(const utils::file::i_fs_item &dir_entry,
|
||||||
const encrypt_config &cfg,
|
const encrypt_config &cfg,
|
||||||
std::string &api_path) const -> bool;
|
std::string &api_path) const -> bool;
|
||||||
|
|
||||||
void remove_deleted_files();
|
void remove_deleted_files(const stop_type &stop_requested);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] auto create_directory(const std::string &api_path,
|
[[nodiscard]] auto create_directory(const std::string &api_path,
|
||||||
api_meta_map &meta) -> api_error override;
|
api_meta_map &meta) -> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto create_directory_clone_source_meta(
|
[[nodiscard]] auto
|
||||||
const std::string & /*source_api_path*/,
|
create_directory_clone_source_meta(const std::string & /*source_api_path*/,
|
||||||
const std::string & /*api_path*/) -> api_error override {
|
const std::string & /*api_path*/)
|
||||||
|
-> api_error override {
|
||||||
|
return api_error::not_implemented;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto create_file(const std::string & /*api_path*/,
|
||||||
|
api_meta_map & /*meta*/)
|
||||||
|
-> api_error override {
|
||||||
return api_error::not_implemented;
|
return api_error::not_implemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto
|
||||||
create_file(const std::string & /*api_path*/,
|
get_api_path_from_source(const std::string & /*source_path*/,
|
||||||
api_meta_map & /*meta*/) -> api_error override {
|
std::string & /*api_path*/) const
|
||||||
return api_error::not_implemented;
|
-> api_error override;
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_api_path_from_source(
|
|
||||||
const std::string & /*source_path*/,
|
|
||||||
std::string & /*api_path*/) const -> api_error override;
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_directory_item_count(const std::string &api_path) const
|
[[nodiscard]] auto get_directory_item_count(const std::string &api_path) const
|
||||||
-> std::uint64_t override;
|
-> std::uint64_t override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto get_directory_items(const std::string &api_path,
|
||||||
get_directory_items(const std::string &api_path,
|
directory_item_list &list) const
|
||||||
directory_item_list &list) const -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_file(const std::string &api_path,
|
[[nodiscard]] auto get_file(const std::string &api_path, api_file &file) const
|
||||||
api_file &file) const -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_file_list(api_file_list &list,
|
||||||
|
std::string &marker) const
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_file_size(const std::string &api_path,
|
||||||
|
std::uint64_t &file_size) const
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_filesystem_item(const std::string &api_path,
|
||||||
|
bool directory,
|
||||||
|
filesystem_item &fsi) const
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_filesystem_item_and_file(const std::string &api_path,
|
||||||
|
api_file &file,
|
||||||
|
filesystem_item &fsi) const
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto
|
||||||
get_file_list(api_file_list &list) const -> api_error override;
|
get_filesystem_item_from_source_path(const std::string &source_path,
|
||||||
|
filesystem_item &fsi) const
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto get_pinned_files() const
|
||||||
get_file_size(const std::string &api_path,
|
-> std::vector<std::string> override;
|
||||||
std::uint64_t &file_size) const -> api_error override;
|
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto get_item_meta(const std::string &api_path,
|
||||||
get_filesystem_item(const std::string &api_path, bool directory,
|
api_meta_map &meta) const
|
||||||
filesystem_item &fsi) const -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_filesystem_item_and_file(
|
[[nodiscard]] auto get_item_meta(const std::string &api_path,
|
||||||
const std::string &api_path, api_file &file,
|
const std::string &key,
|
||||||
filesystem_item &fsi) const -> api_error override;
|
std::string &value) const
|
||||||
|
-> api_error override;
|
||||||
[[nodiscard]] auto get_filesystem_item_from_source_path(
|
|
||||||
const std::string &source_path,
|
|
||||||
filesystem_item &fsi) const -> api_error override;
|
|
||||||
|
|
||||||
[[nodiscard]] auto
|
|
||||||
get_pinned_files() const -> std::vector<std::string> override;
|
|
||||||
|
|
||||||
[[nodiscard]] auto
|
|
||||||
get_item_meta(const std::string &api_path,
|
|
||||||
api_meta_map &meta) const -> api_error override;
|
|
||||||
|
|
||||||
[[nodiscard]] auto
|
|
||||||
get_item_meta(const std::string &api_path, const std::string &key,
|
|
||||||
std::string &value) const -> api_error override;
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override;
|
[[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override;
|
||||||
|
|
||||||
@ -149,57 +161,61 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] auto get_used_drive_space() const -> std::uint64_t override;
|
[[nodiscard]] auto get_used_drive_space() const -> std::uint64_t override;
|
||||||
|
|
||||||
[[nodiscard]] auto is_direct_only() const -> bool override { return true; }
|
|
||||||
|
|
||||||
[[nodiscard]] auto is_directory(const std::string &api_path,
|
[[nodiscard]] auto is_directory(const std::string &api_path,
|
||||||
bool &exists) const -> api_error override;
|
bool &exists) const -> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto is_file(const std::string &api_path,
|
[[nodiscard]] auto is_file(const std::string &api_path, bool &exists) const
|
||||||
bool &exists) const -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto is_file_writeable(const std::string &api_path) const
|
||||||
is_file_writeable(const std::string &api_path) const -> bool override;
|
-> bool override;
|
||||||
|
|
||||||
[[nodiscard]] auto is_online() const -> bool override;
|
[[nodiscard]] auto is_online() const -> bool override;
|
||||||
|
|
||||||
[[nodiscard]] auto is_rename_supported() const -> bool override;
|
[[nodiscard]] auto is_read_only() const -> bool override { return true; }
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto is_rename_supported() const -> bool override {
|
||||||
read_file_bytes(const std::string &api_path, std::size_t size,
|
return false;
|
||||||
std::uint64_t offset, data_buffer &data,
|
}
|
||||||
stop_type &stop_requested) -> api_error override;
|
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto read_file_bytes(const std::string &api_path,
|
||||||
remove_directory(const std::string & /*api_path*/) -> api_error override {
|
std::size_t size, std::uint64_t offset,
|
||||||
|
data_buffer &data,
|
||||||
|
stop_type &stop_requested)
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto remove_directory(const std::string & /*api_path*/)
|
||||||
|
-> api_error override {
|
||||||
return api_error::not_implemented;
|
return api_error::not_implemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto remove_file(const std::string & /*api_path*/)
|
||||||
remove_file(const std::string & /*api_path*/) -> api_error override {
|
-> api_error override {
|
||||||
return api_error::not_implemented;
|
return api_error::not_implemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto remove_item_meta(const std::string & /*api_path*/,
|
||||||
remove_item_meta(const std::string & /*api_path*/,
|
const std::string & /*key*/)
|
||||||
const std::string & /*key*/) -> api_error override {
|
-> api_error override {
|
||||||
return api_error::success;
|
return api_error::success;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto rename_file(const std::string & /*from_api_path*/,
|
||||||
rename_file(const std::string & /*from_api_path*/,
|
const std::string & /*to_api_path*/)
|
||||||
const std::string & /*to_api_path*/) -> api_error override {
|
-> api_error override {
|
||||||
return api_error::not_implemented;
|
return api_error::not_implemented;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto set_item_meta(const std::string & /*api_path*/,
|
||||||
set_item_meta(const std::string & /*api_path*/, const std::string & /*key*/,
|
const std::string & /*key*/,
|
||||||
const std::string & /*value*/) -> api_error override {
|
const std::string & /*value*/)
|
||||||
|
-> api_error override {
|
||||||
return api_error::success;
|
return api_error::success;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto set_item_meta(const std::string & /*api_path*/,
|
||||||
set_item_meta(const std::string & /*api_path*/,
|
const api_meta_map & /*meta*/)
|
||||||
const api_meta_map & /*meta*/) -> api_error override {
|
-> api_error override {
|
||||||
return api_error::success;
|
return api_error::success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,10 +224,10 @@ public:
|
|||||||
|
|
||||||
void stop() override;
|
void stop() override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto upload_file(const std::string & /*api_path*/,
|
||||||
upload_file(const std::string & /*api_path*/,
|
|
||||||
const std::string & /*source_path*/,
|
const std::string & /*source_path*/,
|
||||||
stop_type & /*stop_requested*/) -> api_error override {
|
stop_type & /*stop_requested*/)
|
||||||
|
-> api_error override {
|
||||||
return api_error::not_implemented;
|
return api_error::not_implemented;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -31,13 +31,14 @@ class i_provider {
|
|||||||
INTERFACE_SETUP(i_provider);
|
INTERFACE_SETUP(i_provider);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto create_directory(const std::string &api_path,
|
||||||
create_directory(const std::string &api_path,
|
api_meta_map &meta)
|
||||||
api_meta_map &meta) -> api_error = 0;
|
-> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto create_directory_clone_source_meta(
|
[[nodiscard]] virtual auto
|
||||||
const std::string &source_api_path,
|
create_directory_clone_source_meta(const std::string &source_api_path,
|
||||||
const std::string &api_path) -> api_error = 0;
|
const std::string &api_path)
|
||||||
|
-> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto create_file(const std::string &api_path,
|
[[nodiscard]] virtual auto create_file(const std::string &api_path,
|
||||||
api_meta_map &meta) -> api_error = 0;
|
api_meta_map &meta) -> api_error = 0;
|
||||||
@ -46,8 +47,9 @@ public:
|
|||||||
get_api_path_from_source(const std::string &source_path,
|
get_api_path_from_source(const std::string &source_path,
|
||||||
std::string &api_path) const -> api_error = 0;
|
std::string &api_path) const -> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto get_directory_item_count(
|
[[nodiscard]] virtual auto
|
||||||
const std::string &api_path) const -> std::uint64_t = 0;
|
get_directory_item_count(const std::string &api_path) const
|
||||||
|
-> std::uint64_t = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto
|
||||||
get_directory_items(const std::string &api_path,
|
get_directory_items(const std::string &api_path,
|
||||||
@ -56,35 +58,39 @@ public:
|
|||||||
[[nodiscard]] virtual auto get_file(const std::string &api_path,
|
[[nodiscard]] virtual auto get_file(const std::string &api_path,
|
||||||
api_file &file) const -> api_error = 0;
|
api_file &file) const -> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto get_file_list(api_file_list &list,
|
||||||
get_file_list(api_file_list &list) const -> api_error = 0;
|
std::string &marker) const
|
||||||
|
-> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto get_file_size(const std::string &api_path,
|
||||||
get_file_size(const std::string &api_path,
|
std::uint64_t &file_size) const
|
||||||
std::uint64_t &file_size) const -> api_error = 0;
|
-> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto get_filesystem_item(const std::string &api_path,
|
||||||
get_filesystem_item(const std::string &api_path, bool directory,
|
bool directory,
|
||||||
filesystem_item &fsi) const -> api_error = 0;
|
filesystem_item &fsi) const
|
||||||
|
-> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto
|
||||||
get_filesystem_item_and_file(const std::string &api_path, api_file &file,
|
get_filesystem_item_and_file(const std::string &api_path, api_file &file,
|
||||||
filesystem_item &fsi) const -> api_error = 0;
|
filesystem_item &fsi) const -> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto get_filesystem_item_from_source_path(
|
|
||||||
const std::string &source_path,
|
|
||||||
filesystem_item &fsi) const -> api_error = 0;
|
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto
|
||||||
get_item_meta(const std::string &api_path,
|
get_filesystem_item_from_source_path(const std::string &source_path,
|
||||||
api_meta_map &meta) const -> api_error = 0;
|
filesystem_item &fsi) const
|
||||||
|
-> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto get_item_meta(const std::string &api_path,
|
||||||
get_item_meta(const std::string &api_path, const std::string &key,
|
api_meta_map &meta) const
|
||||||
std::string &value) const -> api_error = 0;
|
-> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto get_item_meta(const std::string &api_path,
|
||||||
get_pinned_files() const -> std::vector<std::string> = 0;
|
const std::string &key,
|
||||||
|
std::string &value) const
|
||||||
|
-> api_error = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_pinned_files() const
|
||||||
|
-> std::vector<std::string> = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto get_provider_type() const -> provider_type = 0;
|
[[nodiscard]] virtual auto get_provider_type() const -> provider_type = 0;
|
||||||
|
|
||||||
@ -94,8 +100,6 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] virtual auto get_used_drive_space() const -> std::uint64_t = 0;
|
[[nodiscard]] virtual auto get_used_drive_space() const -> std::uint64_t = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto is_direct_only() const -> bool = 0;
|
|
||||||
|
|
||||||
[[nodiscard]] virtual auto is_directory(const std::string &api_path,
|
[[nodiscard]] virtual auto is_directory(const std::string &api_path,
|
||||||
bool &exists) const -> api_error = 0;
|
bool &exists) const -> api_error = 0;
|
||||||
|
|
||||||
@ -107,6 +111,8 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] virtual auto is_online() const -> bool = 0;
|
[[nodiscard]] virtual auto is_online() const -> bool = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto is_read_only() const -> bool = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto is_rename_supported() const -> bool = 0;
|
[[nodiscard]] virtual auto is_rename_supported() const -> bool = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto
|
||||||
@ -114,36 +120,38 @@ public:
|
|||||||
std::uint64_t offset, data_buffer &data,
|
std::uint64_t offset, data_buffer &data,
|
||||||
stop_type &stop_requested) -> api_error = 0;
|
stop_type &stop_requested) -> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto remove_directory(const std::string &api_path)
|
||||||
remove_directory(const std::string &api_path) -> api_error = 0;
|
-> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto remove_file(const std::string &api_path)
|
||||||
remove_file(const std::string &api_path) -> api_error = 0;
|
-> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto remove_item_meta(const std::string &api_path,
|
||||||
remove_item_meta(const std::string &api_path,
|
const std::string &key)
|
||||||
const std::string &key) -> api_error = 0;
|
-> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto rename_file(const std::string &from_api_path,
|
||||||
rename_file(const std::string &from_api_path,
|
const std::string &to_api_path)
|
||||||
const std::string &to_api_path) -> api_error = 0;
|
-> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto set_item_meta(const std::string &api_path,
|
||||||
set_item_meta(const std::string &api_path, const std::string &key,
|
const std::string &key,
|
||||||
const std::string &value) -> api_error = 0;
|
const std::string &value)
|
||||||
|
-> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto set_item_meta(const std::string &api_path,
|
||||||
set_item_meta(const std::string &api_path,
|
const api_meta_map &meta)
|
||||||
const api_meta_map &meta) -> api_error = 0;
|
-> api_error = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto start(api_item_added_callback api_item_added,
|
[[nodiscard]] virtual auto start(api_item_added_callback api_item_added,
|
||||||
i_file_manager *mgr) -> bool = 0;
|
i_file_manager *mgr) -> bool = 0;
|
||||||
|
|
||||||
virtual void stop() = 0;
|
virtual void stop() = 0;
|
||||||
|
|
||||||
[[nodiscard]] virtual auto
|
[[nodiscard]] virtual auto upload_file(const std::string &api_path,
|
||||||
upload_file(const std::string &api_path, const std::string &source_path,
|
const std::string &source_path,
|
||||||
stop_type &stop_requested) -> api_error = 0;
|
stop_type &stop_requested)
|
||||||
|
-> api_error = 0;
|
||||||
};
|
};
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
|
||||||
|
@ -47,69 +47,77 @@ public:
|
|||||||
auto operator=(s3_provider &&) -> s3_provider & = delete;
|
auto operator=(s3_provider &&) -> s3_provider & = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] auto
|
s3_config s3_config_;
|
||||||
add_if_not_found(api_file &file,
|
|
||||||
const std::string &object_name) const -> api_error;
|
|
||||||
|
|
||||||
[[nodiscard]] auto
|
private:
|
||||||
create_file_extra(const std::string &api_path,
|
[[nodiscard]] auto add_if_not_found(api_file &file,
|
||||||
api_meta_map &meta) -> api_error override;
|
const std::string &object_name) const
|
||||||
|
-> api_error;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto create_file_extra(const std::string &api_path,
|
||||||
create_path_directories(const std::string &api_path,
|
api_meta_map &meta)
|
||||||
const std::string &key) const -> api_error;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto create_path_directories(const std::string &api_path,
|
||||||
decrypt_object_name(std::string &object_name) const -> api_error;
|
const std::string &key) const
|
||||||
|
-> api_error;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto decrypt_object_name(std::string &object_name) const
|
||||||
get_last_modified(bool directory,
|
-> api_error;
|
||||||
const std::string &api_path) const -> std::uint64_t;
|
|
||||||
|
[[nodiscard]] auto get_last_modified(bool directory,
|
||||||
|
const std::string &api_path) const
|
||||||
|
-> std::uint64_t;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto
|
||||||
get_object_info(bool directory, const std::string &api_path,
|
get_object_info(bool directory, const std::string &api_path,
|
||||||
bool &is_encrypted, std::string &object_name,
|
bool &is_encrypted, std::string &object_name,
|
||||||
head_object_result &result) const -> api_error;
|
head_object_result &result) const -> api_error;
|
||||||
|
|
||||||
[[nodiscard]] auto get_object_list(
|
[[nodiscard]] auto
|
||||||
std::string &response_data, long &response_code,
|
get_object_list(std::string &response_data, long &response_code,
|
||||||
std::optional<std::string> delimiter = std::nullopt,
|
std::optional<std::string> delimiter = std::nullopt,
|
||||||
std::optional<std::string> prefix = std::nullopt) const -> bool;
|
std::optional<std::string> prefix = std::nullopt,
|
||||||
|
std::optional<std::string> token = std::nullopt) const
|
||||||
|
-> bool;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_s3_config() const -> const s3_config & {
|
||||||
|
return s3_config_;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto create_directory_impl(const std::string &api_path,
|
||||||
create_directory_impl(const std::string &api_path,
|
api_meta_map &meta)
|
||||||
api_meta_map &meta) -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_directory_items_impl(const std::string &api_path,
|
[[nodiscard]] auto get_directory_items_impl(const std::string &api_path,
|
||||||
directory_item_list &list) const
|
directory_item_list &list) const
|
||||||
-> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto remove_directory_impl(const std::string &api_path)
|
||||||
get_used_drive_space_impl() const -> std::uint64_t override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto remove_file_impl(const std::string &api_path)
|
||||||
remove_directory_impl(const std::string &api_path) -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto upload_file_impl(const std::string &api_path,
|
||||||
remove_file_impl(const std::string &api_path) -> api_error override;
|
const std::string &source_path,
|
||||||
|
stop_type &stop_requested)
|
||||||
[[nodiscard]] auto
|
-> api_error override;
|
||||||
upload_file_impl(const std::string &api_path, const std::string &source_path,
|
|
||||||
stop_type &stop_requested) -> api_error override;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] static auto
|
[[nodiscard]] static auto convert_api_date(std::string_view date)
|
||||||
convert_api_date(std::string_view date) -> std::uint64_t;
|
-> std::uint64_t;
|
||||||
|
|
||||||
[[nodiscard]] auto get_directory_item_count(const std::string &api_path) const
|
[[nodiscard]] auto get_directory_item_count(const std::string &api_path) const
|
||||||
-> std::uint64_t override;
|
-> std::uint64_t override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_file(const std::string &api_path,
|
[[nodiscard]] auto get_file(const std::string &api_path, api_file &file) const
|
||||||
api_file &file) const -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto get_file_list(api_file_list &list,
|
||||||
get_file_list(api_file_list &list) const -> api_error override;
|
std::string &marker) const
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override;
|
[[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override;
|
||||||
|
|
||||||
@ -117,13 +125,11 @@ public:
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto is_direct_only() const -> bool override { return false; }
|
|
||||||
|
|
||||||
[[nodiscard]] auto is_directory(const std::string &api_path,
|
[[nodiscard]] auto is_directory(const std::string &api_path,
|
||||||
bool &exists) const -> api_error override;
|
bool &exists) const -> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto is_file(const std::string &api_path,
|
[[nodiscard]] auto is_file(const std::string &api_path, bool &exists) const
|
||||||
bool &exists) const -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto is_online() const -> bool override;
|
[[nodiscard]] auto is_online() const -> bool override;
|
||||||
|
|
||||||
@ -131,14 +137,15 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto read_file_bytes(const std::string &api_path,
|
||||||
read_file_bytes(const std::string &api_path, std::size_t size,
|
std::size_t size, std::uint64_t offset,
|
||||||
std::uint64_t offset, data_buffer &data,
|
data_buffer &data,
|
||||||
stop_type &stop_requested) -> api_error override;
|
stop_type &stop_requested)
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto rename_file(const std::string &from_api_path,
|
||||||
rename_file(const std::string &from_api_path,
|
const std::string &to_api_path)
|
||||||
const std::string &to_api_path) -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto start(api_item_added_callback api_item_added,
|
[[nodiscard]] auto start(api_item_added_callback api_item_added,
|
||||||
i_file_manager *mgr) -> bool override;
|
i_file_manager *mgr) -> bool override;
|
||||||
|
@ -45,6 +45,9 @@ public:
|
|||||||
auto operator=(const sia_provider &) -> sia_provider & = delete;
|
auto operator=(const sia_provider &) -> sia_provider & = delete;
|
||||||
auto operator=(sia_provider &&) -> sia_provider & = delete;
|
auto operator=(sia_provider &&) -> sia_provider & = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
sia_config sia_config_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] auto get_object_info(const std::string &api_path,
|
[[nodiscard]] auto get_object_info(const std::string &api_path,
|
||||||
json &object_info) const -> api_error;
|
json &object_info) const -> api_error;
|
||||||
@ -52,37 +55,40 @@ private:
|
|||||||
[[nodiscard]] auto get_object_list(const std::string &api_path,
|
[[nodiscard]] auto get_object_list(const std::string &api_path,
|
||||||
nlohmann::json &object_list) const -> bool;
|
nlohmann::json &object_list) const -> bool;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_sia_config() const -> const auto & {
|
||||||
|
return sia_config_;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto create_directory_impl(const std::string &api_path,
|
||||||
create_directory_impl(const std::string &api_path,
|
api_meta_map &meta)
|
||||||
api_meta_map &meta) -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_directory_items_impl(const std::string &api_path,
|
[[nodiscard]] auto get_directory_items_impl(const std::string &api_path,
|
||||||
directory_item_list &list) const
|
directory_item_list &list) const
|
||||||
-> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto remove_directory_impl(const std::string &api_path)
|
||||||
get_used_drive_space_impl() const -> std::uint64_t override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto remove_file_impl(const std::string &api_path)
|
||||||
remove_directory_impl(const std::string &api_path) -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto upload_file_impl(const std::string &api_path,
|
||||||
remove_file_impl(const std::string &api_path) -> api_error override;
|
const std::string &source_path,
|
||||||
|
stop_type &stop_requested)
|
||||||
[[nodiscard]] auto
|
-> api_error override;
|
||||||
upload_file_impl(const std::string &api_path, const std::string &source_path,
|
|
||||||
stop_type &stop_requested) -> api_error override;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] auto get_directory_item_count(const std::string &api_path) const
|
[[nodiscard]] auto get_directory_item_count(const std::string &api_path) const
|
||||||
-> std::uint64_t override;
|
-> std::uint64_t override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_file(const std::string &api_path,
|
[[nodiscard]] auto get_file(const std::string &api_path, api_file &file) const
|
||||||
api_file &file) const -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto get_file_list(api_file_list &list,
|
||||||
get_file_list(api_file_list &list) const -> api_error override;
|
std::string &marker) const
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto get_provider_type() const -> provider_type override {
|
[[nodiscard]] auto get_provider_type() const -> provider_type override {
|
||||||
return type;
|
return type;
|
||||||
@ -90,13 +96,11 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override;
|
[[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override;
|
||||||
|
|
||||||
[[nodiscard]] auto is_direct_only() const -> bool override { return false; }
|
|
||||||
|
|
||||||
[[nodiscard]] auto is_directory(const std::string &api_path,
|
[[nodiscard]] auto is_directory(const std::string &api_path,
|
||||||
bool &exists) const -> api_error override;
|
bool &exists) const -> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto is_file(const std::string &api_path,
|
[[nodiscard]] auto is_file(const std::string &api_path, bool &exists) const
|
||||||
bool &exists) const -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto is_online() const -> bool override;
|
[[nodiscard]] auto is_online() const -> bool override;
|
||||||
|
|
||||||
@ -104,14 +108,15 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto read_file_bytes(const std::string &api_path,
|
||||||
read_file_bytes(const std::string &api_path, std::size_t size,
|
std::size_t size, std::uint64_t offset,
|
||||||
std::uint64_t offset, data_buffer &buffer,
|
data_buffer &buffer,
|
||||||
stop_type &stop_requested) -> api_error override;
|
stop_type &stop_requested)
|
||||||
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto rename_file(const std::string &from_api_path,
|
||||||
rename_file(const std::string &from_api_path,
|
const std::string &to_api_path)
|
||||||
const std::string &to_api_path) -> api_error override;
|
-> api_error override;
|
||||||
|
|
||||||
[[nodiscard]] auto start(api_item_added_callback api_item_added,
|
[[nodiscard]] auto start(api_item_added_callback api_item_added,
|
||||||
i_file_manager *mgr) -> bool override;
|
i_file_manager *mgr) -> bool override;
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#ifndef REPERTORY_INCLUDE_TYPES_REMOTE_HPP_
|
#ifndef REPERTORY_INCLUDE_TYPES_REMOTE_HPP_
|
||||||
#define REPERTORY_INCLUDE_TYPES_REMOTE_HPP_
|
#define REPERTORY_INCLUDE_TYPES_REMOTE_HPP_
|
||||||
|
|
||||||
|
#include "types/repertory.hpp"
|
||||||
|
|
||||||
inline constexpr const auto PACKET_SERVICE_FUSE{1U};
|
inline constexpr const auto PACKET_SERVICE_FUSE{1U};
|
||||||
inline constexpr const auto PACKET_SERVICE_WINFSP{2U};
|
inline constexpr const auto PACKET_SERVICE_WINFSP{2U};
|
||||||
|
|
||||||
@ -31,7 +33,67 @@ inline constexpr const auto PACKET_SERVICE_FLAGS{PACKET_SERVICE_WINFSP};
|
|||||||
inline constexpr const auto PACKET_SERVICE_FLAGS{PACKET_SERVICE_FUSE};
|
inline constexpr const auto PACKET_SERVICE_FLAGS{PACKET_SERVICE_FUSE};
|
||||||
#endif // defined(_WIN32)
|
#endif // defined(_WIN32)
|
||||||
|
|
||||||
|
constexpr const auto default_remote_client_pool_size{20U};
|
||||||
|
constexpr const auto default_remote_max_connections{20U};
|
||||||
|
constexpr const auto default_remote_receive_timeout_ms{120U * 1000U};
|
||||||
|
constexpr const auto default_remote_send_timeout_ms{30U * 1000U};
|
||||||
|
|
||||||
namespace repertory::remote {
|
namespace repertory::remote {
|
||||||
|
struct remote_config final {
|
||||||
|
std::uint16_t api_port{};
|
||||||
|
std::string encryption_token;
|
||||||
|
std::string host_name_or_ip;
|
||||||
|
std::uint8_t max_connections{default_remote_max_connections};
|
||||||
|
std::uint32_t recv_timeout_ms{default_remote_receive_timeout_ms};
|
||||||
|
std::uint32_t send_timeout_ms{default_remote_send_timeout_ms};
|
||||||
|
|
||||||
|
auto operator==(const remote_config &cfg) const noexcept -> bool {
|
||||||
|
if (&cfg != this) {
|
||||||
|
return api_port == cfg.api_port &&
|
||||||
|
encryption_token == cfg.encryption_token &&
|
||||||
|
host_name_or_ip == cfg.host_name_or_ip &&
|
||||||
|
max_connections == cfg.max_connections &&
|
||||||
|
recv_timeout_ms == cfg.recv_timeout_ms &&
|
||||||
|
send_timeout_ms == cfg.send_timeout_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto operator!=(const remote_config &cfg) const noexcept -> bool {
|
||||||
|
if (&cfg != this) {
|
||||||
|
return not(cfg == *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct remote_mount final {
|
||||||
|
std::uint16_t api_port{};
|
||||||
|
std::uint8_t client_pool_size{default_remote_client_pool_size};
|
||||||
|
bool enable{false};
|
||||||
|
std::string encryption_token;
|
||||||
|
|
||||||
|
auto operator==(const remote_mount &cfg) const noexcept -> bool {
|
||||||
|
if (&cfg == this) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return api_port == cfg.api_port &&
|
||||||
|
client_pool_size == cfg.client_pool_size && enable == cfg.enable &&
|
||||||
|
encryption_token == cfg.encryption_token;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto operator!=(const remote_mount &cfg) const noexcept -> bool {
|
||||||
|
if (&cfg == this) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return not(cfg == *this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
using block_count = std::uint64_t;
|
using block_count = std::uint64_t;
|
||||||
using block_size = std::uint32_t;
|
using block_size = std::uint32_t;
|
||||||
using file_handle = std::uint64_t;
|
using file_handle = std::uint64_t;
|
||||||
@ -160,4 +222,46 @@ create_os_open_flags(const open_flags &flags) -> std::uint32_t;
|
|||||||
#endif // !defined(_WIN32)
|
#endif // !defined(_WIN32)
|
||||||
} // namespace repertory::remote
|
} // namespace repertory::remote
|
||||||
|
|
||||||
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
|
template <> struct adl_serializer<repertory::remote::remote_config> {
|
||||||
|
static void to_json(json &data,
|
||||||
|
const repertory::remote::remote_config &value) {
|
||||||
|
data[repertory::JSON_API_PORT] = value.api_port;
|
||||||
|
data[repertory::JSON_ENCRYPTION_TOKEN] = value.encryption_token;
|
||||||
|
data[repertory::JSON_HOST_NAME_OR_IP] = value.host_name_or_ip;
|
||||||
|
data[repertory::JSON_MAX_CONNECTIONS] = value.max_connections;
|
||||||
|
data[repertory::JSON_RECV_TIMEOUT_MS] = value.recv_timeout_ms;
|
||||||
|
data[repertory::JSON_SEND_TIMEOUT_MS] = value.send_timeout_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void from_json(const json &data,
|
||||||
|
repertory::remote::remote_config &value) {
|
||||||
|
data.at(repertory::JSON_API_PORT).get_to(value.api_port);
|
||||||
|
data.at(repertory::JSON_ENCRYPTION_TOKEN).get_to(value.encryption_token);
|
||||||
|
data.at(repertory::JSON_HOST_NAME_OR_IP).get_to(value.host_name_or_ip);
|
||||||
|
data.at(repertory::JSON_MAX_CONNECTIONS).get_to(value.max_connections);
|
||||||
|
data.at(repertory::JSON_RECV_TIMEOUT_MS).get_to(value.recv_timeout_ms);
|
||||||
|
data.at(repertory::JSON_SEND_TIMEOUT_MS).get_to(value.send_timeout_ms);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> struct adl_serializer<repertory::remote::remote_mount> {
|
||||||
|
static void to_json(json &data,
|
||||||
|
const repertory::remote::remote_mount &value) {
|
||||||
|
data[repertory::JSON_API_PORT] = value.api_port;
|
||||||
|
data[repertory::JSON_CLIENT_POOL_SIZE] = value.client_pool_size;
|
||||||
|
data[repertory::JSON_ENABLE_REMOTE_MOUNT] = value.enable;
|
||||||
|
data[repertory::JSON_ENCRYPTION_TOKEN] = value.encryption_token;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void from_json(const json &data,
|
||||||
|
repertory::remote::remote_mount &value) {
|
||||||
|
data.at(repertory::JSON_API_PORT).get_to(value.api_port);
|
||||||
|
data.at(repertory::JSON_CLIENT_POOL_SIZE).get_to(value.client_pool_size);
|
||||||
|
data.at(repertory::JSON_ENABLE_REMOTE_MOUNT).get_to(value.enable);
|
||||||
|
data.at(repertory::JSON_ENCRYPTION_TOKEN).get_to(value.encryption_token);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|
||||||
#endif // REPERTORY_INCLUDE_TYPES_REMOTE_HPP_
|
#endif // REPERTORY_INCLUDE_TYPES_REMOTE_HPP_
|
||||||
|
@ -23,7 +23,125 @@
|
|||||||
#define REPERTORY_INCLUDE_TYPES_REPERTORY_HPP_
|
#define REPERTORY_INCLUDE_TYPES_REPERTORY_HPP_
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
inline constexpr const auto max_time{std::numeric_limits<std::uint64_t>::max()};
|
constexpr const auto default_api_auth_size{48U};
|
||||||
|
constexpr const auto default_download_timeout_ces{30U};
|
||||||
|
constexpr const auto default_eviction_delay_mins{1U};
|
||||||
|
constexpr const auto default_high_freq_interval_secs{30U};
|
||||||
|
constexpr const auto default_low_freq_interval_secs{0U * 60U};
|
||||||
|
constexpr const auto default_max_cache_size_bytes{
|
||||||
|
std::uint64_t(20UL * 1024UL * 1024UL * 1024UL),
|
||||||
|
};
|
||||||
|
constexpr const auto default_max_upload_count{5U};
|
||||||
|
constexpr const auto default_med_freq_interval_secs{2U * 60U};
|
||||||
|
constexpr const auto default_online_check_retry_secs{60U};
|
||||||
|
constexpr const auto default_orphaned_file_retention_days{15U};
|
||||||
|
constexpr const auto default_retry_read_count{6U};
|
||||||
|
constexpr const auto default_ring_buffer_file_size{512U};
|
||||||
|
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 min_cache_size_bytes{
|
||||||
|
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)};
|
||||||
|
constexpr const auto min_retry_read_count{std::uint16_t(2U)};
|
||||||
|
constexpr const auto min_ring_buffer_file_size{std::uint16_t(64U)};
|
||||||
|
constexpr const auto min_task_wait_ms{std::uint16_t(50U)};
|
||||||
|
|
||||||
|
template <typename data_t> class atomic final {
|
||||||
|
public:
|
||||||
|
atomic() : mtx_(std::make_shared<std::mutex>()) {}
|
||||||
|
|
||||||
|
atomic(const atomic &at_data)
|
||||||
|
: data_(at_data.load()), mtx_(std::make_shared<std::mutex>()) {}
|
||||||
|
|
||||||
|
atomic(data_t data)
|
||||||
|
: data_(std::move(data)), mtx_(std::make_shared<std::mutex>()) {}
|
||||||
|
|
||||||
|
atomic(atomic &&) = default;
|
||||||
|
|
||||||
|
~atomic() = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
data_t data_;
|
||||||
|
std::shared_ptr<std::mutex> mtx_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
[[nodiscard]] auto load() const -> data_t {
|
||||||
|
mutex_lock lock(*mtx_);
|
||||||
|
return data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto store(data_t data) -> data_t {
|
||||||
|
mutex_lock lock(*mtx_);
|
||||||
|
data_ = std::move(data);
|
||||||
|
return data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto operator=(const atomic &at_data) -> atomic & {
|
||||||
|
if (&at_data == this) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
store(at_data.load());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto operator=(atomic &&) -> atomic & = default;
|
||||||
|
|
||||||
|
auto operator=(data_t data) -> atomic & {
|
||||||
|
if (&data == &data_) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
store(std::move(data));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto operator==(const atomic &at_data) const -> bool {
|
||||||
|
if (&at_data == this) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_lock lock(*mtx_);
|
||||||
|
return at_data.load() == data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto operator==(const data_t &data) const -> bool {
|
||||||
|
if (&data == &data_) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_lock lock(*mtx_);
|
||||||
|
return data == data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto operator!=(const atomic &at_data) const -> bool {
|
||||||
|
if (&at_data == this) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_lock lock(*mtx_);
|
||||||
|
return at_data.load() != data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto operator!=(const data_t &data) const -> bool {
|
||||||
|
if (&data == &data_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_lock lock(*mtx_);
|
||||||
|
return data != data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] operator data_t() const { return load(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
inline constexpr const auto max_time{
|
||||||
|
std::numeric_limits<std::uint64_t>::max(),
|
||||||
|
};
|
||||||
|
|
||||||
inline constexpr const std::string META_ACCESSED{"accessed"};
|
inline constexpr const std::string META_ACCESSED{"accessed"};
|
||||||
inline constexpr const std::string META_ATTRIBUTES{"attributes"};
|
inline constexpr const std::string META_ATTRIBUTES{"attributes"};
|
||||||
@ -57,6 +175,7 @@ enum class api_error {
|
|||||||
bad_address,
|
bad_address,
|
||||||
buffer_overflow,
|
buffer_overflow,
|
||||||
buffer_too_small,
|
buffer_too_small,
|
||||||
|
cache_not_initialized,
|
||||||
comm_error,
|
comm_error,
|
||||||
decryption_error,
|
decryption_error,
|
||||||
directory_end_of_files,
|
directory_end_of_files,
|
||||||
@ -75,10 +194,12 @@ enum class api_error {
|
|||||||
invalid_handle,
|
invalid_handle,
|
||||||
invalid_operation,
|
invalid_operation,
|
||||||
invalid_ring_buffer_multiple,
|
invalid_ring_buffer_multiple,
|
||||||
|
invalid_ring_buffer_position,
|
||||||
invalid_ring_buffer_size,
|
invalid_ring_buffer_size,
|
||||||
invalid_version,
|
invalid_version,
|
||||||
item_exists,
|
item_exists,
|
||||||
item_not_found,
|
item_not_found,
|
||||||
|
more_data,
|
||||||
no_disk_space,
|
no_disk_space,
|
||||||
not_implemented,
|
not_implemented,
|
||||||
not_supported,
|
not_supported,
|
||||||
@ -98,16 +219,31 @@ enum class api_error {
|
|||||||
[[nodiscard]] auto
|
[[nodiscard]] auto
|
||||||
api_error_to_string(const api_error &error) -> const std::string &;
|
api_error_to_string(const api_error &error) -> const std::string &;
|
||||||
|
|
||||||
enum class download_type { direct, fallback, ring_buffer };
|
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
|
[[nodiscard]] auto
|
||||||
download_type_from_string(std::string type,
|
database_type_to_string(const database_type &type) -> std::string;
|
||||||
const download_type &default_type) -> download_type;
|
|
||||||
|
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
|
[[nodiscard]] auto
|
||||||
download_type_to_string(const download_type &type) -> std::string;
|
download_type_to_string(const download_type &type) -> std::string;
|
||||||
|
|
||||||
enum class exit_code : std::int32_t {
|
enum class exit_code : std::int32_t {
|
||||||
success,
|
success = 0,
|
||||||
communication_error = -1,
|
communication_error = -1,
|
||||||
file_creation_failed = -2,
|
file_creation_failed = -2,
|
||||||
incompatible_version = -3,
|
incompatible_version = -3,
|
||||||
@ -157,129 +293,136 @@ using open_file_data = int;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct api_file final {
|
struct api_file final {
|
||||||
std::string api_path{};
|
std::string api_path;
|
||||||
std::string api_parent{};
|
std::string api_parent;
|
||||||
std::uint64_t accessed_date{};
|
std::uint64_t accessed_date{};
|
||||||
std::uint64_t changed_date{};
|
std::uint64_t changed_date{};
|
||||||
std::uint64_t creation_date{};
|
std::uint64_t creation_date{};
|
||||||
std::uint64_t file_size{};
|
std::uint64_t file_size{};
|
||||||
std::string key{};
|
std::string key;
|
||||||
std::uint64_t modified_date{};
|
std::uint64_t modified_date{};
|
||||||
std::string source_path;
|
std::string source_path;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct directory_item final {
|
struct directory_item final {
|
||||||
std::string api_path{};
|
std::string api_path;
|
||||||
std::string api_parent{};
|
std::string api_parent;
|
||||||
bool directory{false};
|
bool directory{false};
|
||||||
std::uint64_t size{};
|
std::uint64_t size{};
|
||||||
api_meta_map meta{};
|
api_meta_map meta;
|
||||||
bool resolved{false};
|
bool resolved{false};
|
||||||
|
|
||||||
[[nodiscard]] static auto from_json(const json &item) -> directory_item {
|
|
||||||
directory_item ret{};
|
|
||||||
ret.api_path = item["path"].get<std::string>();
|
|
||||||
ret.api_parent = item["parent"].get<std::string>();
|
|
||||||
ret.directory = item["directory"].get<bool>();
|
|
||||||
ret.size = item["size"].get<std::uint64_t>();
|
|
||||||
ret.meta = item["meta"].get<api_meta_map>();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] auto to_json() const -> json {
|
|
||||||
return {
|
|
||||||
{"path", api_path}, {"parent", api_parent}, {"size", size},
|
|
||||||
{"directory", directory}, {"meta", meta},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct encrypt_config final {
|
struct encrypt_config final {
|
||||||
std::string encryption_token{};
|
std::string encryption_token;
|
||||||
std::string path{};
|
std::string path;
|
||||||
};
|
|
||||||
|
|
||||||
struct filesystem_item final {
|
auto operator==(const encrypt_config &cfg) const noexcept -> bool {
|
||||||
std::string api_path{};
|
if (&cfg != this) {
|
||||||
std::string api_parent{};
|
return encryption_token == cfg.encryption_token && path == cfg.path;
|
||||||
bool directory{false};
|
|
||||||
std::uint64_t size{};
|
|
||||||
std::string source_path{};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct host_config final {
|
|
||||||
std::string agent_string{};
|
|
||||||
std::string api_password{};
|
|
||||||
std::string api_user{};
|
|
||||||
std::uint16_t api_port{};
|
|
||||||
std::string host_name_or_ip{"localhost"};
|
|
||||||
std::string path{};
|
|
||||||
std::string protocol{"http"};
|
|
||||||
std::uint32_t timeout_ms{60000U};
|
|
||||||
|
|
||||||
auto operator==(const host_config &hc) const noexcept -> bool {
|
|
||||||
if (&hc != this) {
|
|
||||||
return agent_string == hc.agent_string &&
|
|
||||||
api_password == hc.api_password && api_user == hc.api_user &&
|
|
||||||
api_port == hc.api_port && host_name_or_ip == hc.host_name_or_ip &&
|
|
||||||
path == hc.path && protocol == hc.protocol &&
|
|
||||||
timeout_ms == hc.timeout_ms;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto operator!=(const host_config &hc) const noexcept -> bool {
|
auto operator!=(const encrypt_config &cfg) const noexcept -> bool {
|
||||||
if (&hc != this) {
|
if (&cfg != this) {
|
||||||
return not(hc == *this);
|
return not(cfg == *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(__GNUG__)
|
struct filesystem_item final {
|
||||||
__attribute__((unused))
|
std::string api_path;
|
||||||
#endif
|
std::string api_parent;
|
||||||
static void
|
bool directory{false};
|
||||||
to_json(json &j, const host_config &hc) {
|
std::uint64_t size{};
|
||||||
j = json{{"AgentString", hc.agent_string},
|
std::string source_path;
|
||||||
{"ApiPassword", hc.api_password},
|
};
|
||||||
{"ApiPort", hc.api_port},
|
|
||||||
{"ApiUser", hc.api_user},
|
|
||||||
{"HostNameOrIp", hc.host_name_or_ip},
|
|
||||||
{"Path", hc.path},
|
|
||||||
{"Protocol", hc.protocol},
|
|
||||||
{"TimeoutMs", hc.timeout_ms}};
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__GNUG__)
|
struct host_config final {
|
||||||
__attribute__((unused))
|
std::string agent_string;
|
||||||
#endif
|
std::string api_password;
|
||||||
static void
|
std::string api_user;
|
||||||
from_json(const json &j, host_config &hc) {
|
std::uint16_t api_port;
|
||||||
j.at("AgentString").get_to(hc.agent_string);
|
std::string host_name_or_ip{"localhost"};
|
||||||
j.at("ApiPassword").get_to(hc.api_password);
|
std::string path;
|
||||||
j.at("ApiPort").get_to(hc.api_port);
|
std::string protocol{"http"};
|
||||||
j.at("AuthUser").get_to(hc.api_user);
|
std::uint32_t timeout_ms{default_timeout_ms};
|
||||||
j.at("HostNameOrIp").get_to(hc.host_name_or_ip);
|
|
||||||
j.at("Path").get_to(hc.path);
|
auto operator==(const host_config &cfg) const noexcept -> bool {
|
||||||
j.at("Protocol").get_to(hc.protocol);
|
if (&cfg != this) {
|
||||||
j.at("TimeoutMs").get_to(hc.timeout_ms);
|
return agent_string == cfg.agent_string &&
|
||||||
}
|
api_password == cfg.api_password && api_user == cfg.api_user &&
|
||||||
|
api_port == cfg.api_port &&
|
||||||
|
host_name_or_ip == cfg.host_name_or_ip && path == cfg.path &&
|
||||||
|
protocol == cfg.protocol && timeout_ms == cfg.timeout_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto operator!=(const host_config &cfg) const noexcept -> bool {
|
||||||
|
if (&cfg != this) {
|
||||||
|
return not(cfg == *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct s3_config final {
|
struct s3_config final {
|
||||||
std::string access_key{};
|
std::string access_key;
|
||||||
std::string bucket{};
|
std::string bucket;
|
||||||
std::string encryption_token{};
|
std::string encryption_token;
|
||||||
std::string region{"any"};
|
std::string region{"any"};
|
||||||
std::string secret_key{};
|
std::string secret_key;
|
||||||
std::uint32_t timeout_ms{60000U};
|
std::uint32_t timeout_ms{default_timeout_ms};
|
||||||
std::string url{};
|
std::string url;
|
||||||
bool use_path_style{false};
|
bool use_path_style{false};
|
||||||
bool use_region_in_url{false};
|
bool use_region_in_url{false};
|
||||||
|
|
||||||
|
auto operator==(const s3_config &cfg) const noexcept -> bool {
|
||||||
|
if (&cfg != this) {
|
||||||
|
return access_key == cfg.access_key && bucket == cfg.bucket &&
|
||||||
|
encryption_token == cfg.encryption_token && region == cfg.region &&
|
||||||
|
secret_key == cfg.secret_key && timeout_ms == cfg.timeout_ms &&
|
||||||
|
url == cfg.url && use_path_style == cfg.use_path_style &&
|
||||||
|
use_region_in_url == cfg.use_region_in_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto operator!=(const s3_config &cfg) const noexcept -> bool {
|
||||||
|
if (&cfg != this) {
|
||||||
|
return not(cfg == *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sia_config final {
|
struct sia_config final {
|
||||||
std::string bucket{};
|
std::string bucket;
|
||||||
|
|
||||||
|
auto operator==(const sia_config &cfg) const noexcept -> bool {
|
||||||
|
if (&cfg != this) {
|
||||||
|
return bucket == cfg.bucket;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto operator!=(const sia_config &cfg) const noexcept -> bool {
|
||||||
|
if (&cfg != this) {
|
||||||
|
return not(cfg == *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using api_file_list = std::vector<api_file>;
|
using api_file_list = std::vector<api_file>;
|
||||||
@ -287,6 +430,226 @@ using api_file_provider_callback = std::function<void(api_file &)>;
|
|||||||
using api_item_added_callback = std::function<api_error(bool, api_file &)>;
|
using api_item_added_callback = std::function<api_error(bool, api_file &)>;
|
||||||
using directory_item_list = std::vector<directory_item>;
|
using directory_item_list = std::vector<directory_item>;
|
||||||
using meta_provider_callback = std::function<void(directory_item &)>;
|
using meta_provider_callback = std::function<void(directory_item &)>;
|
||||||
|
|
||||||
|
inline constexpr const auto JSON_ACCESS_KEY{"AccessKey"};
|
||||||
|
inline constexpr const auto JSON_AGENT_STRING{"AgentString"};
|
||||||
|
inline constexpr const auto JSON_API_AUTH{"ApiAuth"};
|
||||||
|
inline constexpr const auto JSON_API_PARENT{"ApiParent"};
|
||||||
|
inline constexpr const auto JSON_API_PASSWORD{"ApiPassword"};
|
||||||
|
inline constexpr const auto JSON_API_PATH{"ApiPath"};
|
||||||
|
inline constexpr const auto JSON_API_PORT{"ApiPort"};
|
||||||
|
inline constexpr const auto JSON_API_USER{"ApiUser"};
|
||||||
|
inline constexpr const auto JSON_BUCKET{"Bucket"};
|
||||||
|
inline constexpr const auto JSON_CLIENT_POOL_SIZE{"ClientPoolSize"};
|
||||||
|
inline constexpr const auto JSON_DATABASE_TYPE{"DatabaseType"};
|
||||||
|
inline constexpr const auto JSON_DIRECTORY{"Directory"};
|
||||||
|
inline constexpr const auto JSON_DOWNLOAD_TIMEOUT_SECS{
|
||||||
|
"DownloadTimeoutSeconds"};
|
||||||
|
inline constexpr const auto JSON_ENABLE_DRIVE_EVENTS{"EnableDriveEvents"};
|
||||||
|
inline constexpr const auto JSON_ENABLE_DOWNLOAD_TIMEOUT{
|
||||||
|
"EnableDownloadTimeout"};
|
||||||
|
inline constexpr const auto JSON_ENABLE_MOUNT_MANAGER{"EnableMountManager"};
|
||||||
|
inline constexpr const auto JSON_ENABLE_REMOTE_MOUNT{"Enable"};
|
||||||
|
inline constexpr const auto JSON_ENCRYPTION_TOKEN{"EncryptionToken"};
|
||||||
|
inline constexpr const auto JSON_ENCRYPT_CONFIG{"EncryptConfig"};
|
||||||
|
inline constexpr const auto JSON_EVENT_LEVEL{"EventLevel"};
|
||||||
|
inline constexpr const auto JSON_EVICTION_DELAY_MINS{"EvictionDelayMinutes"};
|
||||||
|
inline constexpr const auto JSON_EVICTION_USE_ACCESS_TIME{
|
||||||
|
"EvictionUseAccessedTime"};
|
||||||
|
inline constexpr const auto JSON_HIGH_FREQ_INTERVAL_SECS{
|
||||||
|
"HighFreqIntervalSeconds"};
|
||||||
|
inline constexpr const auto JSON_HOST_CONFIG{"HostConfig"};
|
||||||
|
inline constexpr const auto JSON_HOST_NAME_OR_IP{"HostNameOrIp"};
|
||||||
|
inline constexpr const auto JSON_LOW_FREQ_INTERVAL_SECS{
|
||||||
|
"LowFreqIntervalSeconds"};
|
||||||
|
inline constexpr const auto JSON_MAX_CACHE_SIZE_BYTES{"MaxCacheSizeBytes"};
|
||||||
|
inline constexpr const auto JSON_MAX_CONNECTIONS{"MaxConnections"};
|
||||||
|
inline constexpr const auto JSON_MAX_UPLOAD_COUNT{"MaxUploadCount"};
|
||||||
|
inline constexpr const auto JSON_MED_FREQ_INTERVAL_SECS{
|
||||||
|
"MedFreqIntervalSeconds"};
|
||||||
|
inline constexpr const auto JSON_META{"Meta"};
|
||||||
|
inline constexpr const auto JSON_ONLINE_CHECK_RETRY_SECS{
|
||||||
|
"OnlineCheckRetrySeconds"};
|
||||||
|
inline constexpr const auto JSON_ORPHANED_FILE_RETENTION_DAYS{
|
||||||
|
"OrphanedFileRetentionDays"};
|
||||||
|
inline constexpr const auto JSON_PATH{"Path"};
|
||||||
|
inline constexpr const auto JSON_PREFERRED_DOWNLOAD_TYPE{
|
||||||
|
"PreferredDownloadType"};
|
||||||
|
inline constexpr const auto JSON_PROTOCOL{"Protocol"};
|
||||||
|
inline constexpr const auto JSON_RECV_TIMEOUT_MS{"ReceiveTimeoutMs"};
|
||||||
|
inline constexpr const auto JSON_REGION{"Region"};
|
||||||
|
inline constexpr const auto JSON_REMOTE_CONFIG{"RemoteConfig"};
|
||||||
|
inline constexpr const auto JSON_REMOTE_MOUNT{"RemoteMount"};
|
||||||
|
inline constexpr const auto JSON_RETRY_READ_COUNT{"RetryReadCount"};
|
||||||
|
inline constexpr const auto JSON_RING_BUFFER_FILE_SIZE{"RingBufferFileSize"};
|
||||||
|
inline constexpr const auto JSON_S3_CONFIG{"S3Config"};
|
||||||
|
inline constexpr const auto JSON_SECRET_KEY{"SecretKey"};
|
||||||
|
inline constexpr const auto JSON_SEND_TIMEOUT_MS{"SendTimeoutMs"};
|
||||||
|
inline constexpr const auto JSON_SIA_CONFIG{"SiaConfig"};
|
||||||
|
inline constexpr const auto JSON_SIZE{"Size"};
|
||||||
|
inline constexpr const auto JSON_TASK_WAIT_MS{"TaskWaitMs"};
|
||||||
|
inline constexpr const auto JSON_TIMEOUT_MS{"TimeoutMs"};
|
||||||
|
inline constexpr const auto JSON_URL{"URL"};
|
||||||
|
inline constexpr const auto JSON_USE_PATH_STYLE{"UsePathStyle"};
|
||||||
|
inline constexpr const auto JSON_USE_REGION_IN_URL{"UseRegionInURL"};
|
||||||
|
inline constexpr const auto JSON_VERSION{"Version"};
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
|
||||||
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
|
template <> struct adl_serializer<repertory::directory_item> {
|
||||||
|
static void to_json(json &data, const repertory::directory_item &value) {
|
||||||
|
data[repertory::JSON_API_PARENT] = value.api_parent;
|
||||||
|
data[repertory::JSON_API_PATH] = value.api_path;
|
||||||
|
data[repertory::JSON_DIRECTORY] = value.directory;
|
||||||
|
data[repertory::JSON_META] = value.meta;
|
||||||
|
data[repertory::JSON_SIZE] = value.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void from_json(const json &data, repertory::directory_item &value) {
|
||||||
|
data.at(repertory::JSON_API_PARENT).get_to<std::string>(value.api_parent);
|
||||||
|
data.at(repertory::JSON_API_PATH).get_to<std::string>(value.api_path);
|
||||||
|
data.at(repertory::JSON_DIRECTORY).get_to<bool>(value.directory);
|
||||||
|
data.at(repertory::JSON_META).get_to<repertory::api_meta_map>(value.meta);
|
||||||
|
data.at(repertory::JSON_SIZE).get_to<std::uint64_t>(value.size);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> struct adl_serializer<repertory::encrypt_config> {
|
||||||
|
static void to_json(json &data, const repertory::encrypt_config &value) {
|
||||||
|
data[repertory::JSON_ENCRYPTION_TOKEN] = value.encryption_token;
|
||||||
|
data[repertory::JSON_PATH] = value.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void from_json(const json &data, repertory::encrypt_config &value) {
|
||||||
|
data.at(repertory::JSON_ENCRYPTION_TOKEN).get_to(value.encryption_token);
|
||||||
|
data.at(repertory::JSON_PATH).get_to(value.path);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> struct adl_serializer<repertory::host_config> {
|
||||||
|
static void to_json(json &data, const repertory::host_config &value) {
|
||||||
|
data[repertory::JSON_AGENT_STRING] = value.agent_string;
|
||||||
|
data[repertory::JSON_API_PASSWORD] = value.api_password;
|
||||||
|
data[repertory::JSON_API_PORT] = value.api_port;
|
||||||
|
data[repertory::JSON_API_USER] = value.api_user;
|
||||||
|
data[repertory::JSON_HOST_NAME_OR_IP] = value.host_name_or_ip;
|
||||||
|
data[repertory::JSON_PATH] = value.path;
|
||||||
|
data[repertory::JSON_PROTOCOL] = value.protocol;
|
||||||
|
data[repertory::JSON_TIMEOUT_MS] = value.timeout_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void from_json(const json &data, repertory::host_config &value) {
|
||||||
|
data.at(repertory::JSON_AGENT_STRING).get_to(value.agent_string);
|
||||||
|
data.at(repertory::JSON_API_PASSWORD).get_to(value.api_password);
|
||||||
|
data.at(repertory::JSON_API_PORT).get_to(value.api_port);
|
||||||
|
data.at(repertory::JSON_API_USER).get_to(value.api_user);
|
||||||
|
data.at(repertory::JSON_HOST_NAME_OR_IP).get_to(value.host_name_or_ip);
|
||||||
|
data.at(repertory::JSON_PATH).get_to(value.path);
|
||||||
|
data.at(repertory::JSON_PROTOCOL).get_to(value.protocol);
|
||||||
|
data.at(repertory::JSON_TIMEOUT_MS).get_to(value.timeout_ms);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> struct adl_serializer<repertory::s3_config> {
|
||||||
|
static void to_json(json &data, const repertory::s3_config &value) {
|
||||||
|
data[repertory::JSON_ACCESS_KEY] = value.access_key;
|
||||||
|
data[repertory::JSON_BUCKET] = value.bucket;
|
||||||
|
data[repertory::JSON_ENCRYPTION_TOKEN] = value.encryption_token;
|
||||||
|
data[repertory::JSON_REGION] = value.region;
|
||||||
|
data[repertory::JSON_SECRET_KEY] = value.secret_key;
|
||||||
|
data[repertory::JSON_TIMEOUT_MS] = value.timeout_ms;
|
||||||
|
data[repertory::JSON_URL] = value.url;
|
||||||
|
data[repertory::JSON_USE_PATH_STYLE] = value.use_path_style;
|
||||||
|
data[repertory::JSON_USE_REGION_IN_URL] = value.use_region_in_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void from_json(const json &data, repertory::s3_config &value) {
|
||||||
|
data.at(repertory::JSON_ACCESS_KEY).get_to(value.access_key);
|
||||||
|
data.at(repertory::JSON_BUCKET).get_to(value.bucket);
|
||||||
|
data.at(repertory::JSON_ENCRYPTION_TOKEN).get_to(value.encryption_token);
|
||||||
|
data.at(repertory::JSON_REGION).get_to(value.region);
|
||||||
|
data.at(repertory::JSON_SECRET_KEY).get_to(value.secret_key);
|
||||||
|
data.at(repertory::JSON_TIMEOUT_MS).get_to(value.timeout_ms);
|
||||||
|
data.at(repertory::JSON_URL).get_to(value.url);
|
||||||
|
data.at(repertory::JSON_USE_PATH_STYLE).get_to(value.use_path_style);
|
||||||
|
data.at(repertory::JSON_USE_REGION_IN_URL).get_to(value.use_region_in_url);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> struct adl_serializer<repertory::sia_config> {
|
||||||
|
static void to_json(json &data, const repertory::sia_config &value) {
|
||||||
|
data[repertory::JSON_BUCKET] = value.bucket;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void from_json(const json &data, repertory::sia_config &value) {
|
||||||
|
data.at(repertory::JSON_BUCKET).get_to(value.bucket);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename data_t> struct adl_serializer<repertory::atomic<data_t>> {
|
||||||
|
static void to_json(json &data, const repertory::atomic<data_t> &value) {
|
||||||
|
data = value.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void from_json(const json &data, repertory::atomic<data_t> &value) {
|
||||||
|
value.store(data.get<data_t>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename primitive_t>
|
||||||
|
struct adl_serializer<std::atomic<primitive_t>> {
|
||||||
|
static void to_json(json &data, const std::atomic<primitive_t> &value) {
|
||||||
|
data = value.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void from_json(const json &data, std::atomic<primitive_t> &value) {
|
||||||
|
value.store(data.get<primitive_t>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> struct adl_serializer<std::atomic<repertory::database_type>> {
|
||||||
|
static void to_json(json &data,
|
||||||
|
const std::atomic<repertory::database_type> &value) {
|
||||||
|
data = repertory::database_type_to_string(value.load());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void from_json(const json &data,
|
||||||
|
std::atomic<repertory::database_type> &value) {
|
||||||
|
value.store(repertory::database_type_from_string(data.get<std::string>()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> struct adl_serializer<std::atomic<repertory::download_type>> {
|
||||||
|
static void to_json(json &data,
|
||||||
|
const std::atomic<repertory::download_type> &value) {
|
||||||
|
data = repertory::download_type_to_string(value.load());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void from_json(const json &data,
|
||||||
|
std::atomic<repertory::download_type> &value) {
|
||||||
|
value.store(repertory::download_type_from_string(data.get<std::string>()));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> struct adl_serializer<repertory::database_type> {
|
||||||
|
static void to_json(json &data, const repertory::database_type &value) {
|
||||||
|
data = repertory::database_type_to_string(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void from_json(const json &data, repertory::database_type &value) {
|
||||||
|
value = repertory::database_type_from_string(data.get<std::string>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> struct adl_serializer<repertory::download_type> {
|
||||||
|
static void to_json(json &data, const repertory::download_type &value) {
|
||||||
|
data = repertory::download_type_to_string(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void from_json(const json &data, repertory::download_type &value) {
|
||||||
|
value = repertory::download_type_from_string(data.get<std::string>());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|
||||||
#endif // REPERTORY_INCLUDE_TYPES_REPERTORY_HPP_
|
#endif // REPERTORY_INCLUDE_TYPES_REPERTORY_HPP_
|
||||||
|
@ -26,18 +26,21 @@
|
|||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
class app_config;
|
class app_config;
|
||||||
|
|
||||||
class polling final {
|
class polling final {
|
||||||
public:
|
public:
|
||||||
enum struct frequency {
|
enum struct frequency {
|
||||||
high,
|
high,
|
||||||
low,
|
low,
|
||||||
|
medium,
|
||||||
second,
|
second,
|
||||||
|
size,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct polling_item {
|
struct polling_item final {
|
||||||
std::string name;
|
std::string name;
|
||||||
frequency freq;
|
frequency freq;
|
||||||
std::function<void()> action;
|
std::function<void(const stop_type &stop_requested)> action;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -58,15 +61,15 @@ public:
|
|||||||
static auto instance() -> polling & { return instance_; }
|
static auto instance() -> polling & { return instance_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
app_config *config_ = nullptr;
|
app_config *config_{nullptr};
|
||||||
std::unique_ptr<std::thread> high_frequency_thread_;
|
std::array<std::unique_ptr<std::thread>,
|
||||||
|
static_cast<std::size_t>(frequency::size)>
|
||||||
|
frequency_threads_;
|
||||||
std::unordered_map<std::string, polling_item> items_;
|
std::unordered_map<std::string, polling_item> items_;
|
||||||
std::unique_ptr<std::thread> low_frequency_thread_;
|
|
||||||
std::mutex mutex_;
|
std::mutex mutex_;
|
||||||
std::condition_variable notify_;
|
std::condition_variable notify_;
|
||||||
std::unique_ptr<std::thread> second_frequency_thread_;
|
|
||||||
std::mutex start_stop_mutex_;
|
std::mutex start_stop_mutex_;
|
||||||
stop_type stop_requested_ = false;
|
stop_type stop_requested_{false};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void frequency_thread(std::function<std::uint32_t()> get_frequency_seconds,
|
void frequency_thread(std::function<std::uint32_t()> get_frequency_seconds,
|
||||||
|
116
repertory/librepertory/include/utils/tasks.hpp
Normal file
116
repertory/librepertory/include/utils/tasks.hpp
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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_TASKS_HPP_
|
||||||
|
#define REPERTORY_INCLUDE_UTILS_TASKS_HPP_
|
||||||
|
|
||||||
|
#include "common.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
class app_config;
|
||||||
|
|
||||||
|
class tasks final {
|
||||||
|
public:
|
||||||
|
struct task final {
|
||||||
|
std::function<void(const stop_type &task_stopped)> action;
|
||||||
|
};
|
||||||
|
|
||||||
|
class i_task {
|
||||||
|
INTERFACE_SETUP(i_task);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual auto wait() const -> bool = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
using task_ptr = std::shared_ptr<i_task>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
class task_wait final : public i_task {
|
||||||
|
public:
|
||||||
|
task_wait() = default;
|
||||||
|
task_wait(const task_wait &) = delete;
|
||||||
|
task_wait(task_wait &&) = delete;
|
||||||
|
|
||||||
|
~task_wait() override { set_result(false); }
|
||||||
|
|
||||||
|
auto operator=(const task_wait &) -> task_wait & = delete;
|
||||||
|
auto operator=(task_wait &&) -> task_wait & = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool complete{false};
|
||||||
|
mutable std::mutex mtx;
|
||||||
|
mutable std::condition_variable notify;
|
||||||
|
bool success{false};
|
||||||
|
|
||||||
|
public:
|
||||||
|
void set_result(bool result);
|
||||||
|
|
||||||
|
auto wait() const -> bool override;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct scheduled_task final {
|
||||||
|
task item;
|
||||||
|
|
||||||
|
std::shared_ptr<task_wait> wait{
|
||||||
|
std::make_shared<task_wait>(),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
tasks(const tasks &) = delete;
|
||||||
|
tasks(tasks &&) = delete;
|
||||||
|
auto operator=(const tasks &) -> tasks & = delete;
|
||||||
|
auto operator=(tasks &&) -> tasks & = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
tasks() = default;
|
||||||
|
|
||||||
|
~tasks() { stop(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static tasks instance_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static auto instance() -> tasks & { return instance_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
app_config *config_{nullptr};
|
||||||
|
std::atomic<std::uint64_t> count_{0U};
|
||||||
|
std::mutex mutex_;
|
||||||
|
std::condition_variable notify_;
|
||||||
|
std::mutex start_stop_mutex_;
|
||||||
|
stop_type stop_requested_{false};
|
||||||
|
std::vector<std::unique_ptr<std::jthread>> task_threads_;
|
||||||
|
std::deque<scheduled_task> tasks_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void task_thread();
|
||||||
|
|
||||||
|
public:
|
||||||
|
auto schedule(task item) -> task_ptr;
|
||||||
|
|
||||||
|
void start(app_config *config);
|
||||||
|
|
||||||
|
void stop();
|
||||||
|
};
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
|
#endif // REPERTORY_INCLUDE_UTILS_TASKS_HPP_
|
@ -24,15 +24,25 @@
|
|||||||
|
|
||||||
#include "types/repertory.hpp"
|
#include "types/repertory.hpp"
|
||||||
|
|
||||||
namespace repertory::utils {
|
namespace repertory {
|
||||||
|
class app_config;
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
void calculate_allocation_size(bool directory, std::uint64_t file_size,
|
void calculate_allocation_size(bool directory, std::uint64_t file_size,
|
||||||
UINT64 allocation_size,
|
UINT64 allocation_size,
|
||||||
std::string &allocation_meta_size);
|
std::string &allocation_meta_size);
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto
|
||||||
create_volume_label(const provider_type &prov) -> std::string;
|
create_rocksdb(const app_config &cfg, const std::string &name,
|
||||||
|
const std::vector<rocksdb::ColumnFamilyDescriptor> &families,
|
||||||
|
std::vector<rocksdb::ColumnFamilyHandle *> &handles, bool clear)
|
||||||
|
-> std::unique_ptr<rocksdb::TransactionDB>;
|
||||||
|
|
||||||
|
[[nodiscard]] auto create_volume_label(const provider_type &prov)
|
||||||
|
-> std::string;
|
||||||
|
|
||||||
[[nodiscard]] auto get_attributes_from_meta(const api_meta_map &meta) -> DWORD;
|
[[nodiscard]] auto get_attributes_from_meta(const api_meta_map &meta) -> DWORD;
|
||||||
} // namespace repertory::utils
|
} // namespace utils
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
#endif // REPERTORY_INCLUDE_UTILS_UTILS_HPP_
|
#endif // REPERTORY_INCLUDE_UTILS_UTILS_HPP_
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -21,16 +21,19 @@
|
|||||||
*/
|
*/
|
||||||
#include "comm/curl/requests/http_put_file.hpp"
|
#include "comm/curl/requests/http_put_file.hpp"
|
||||||
|
|
||||||
|
#include "utils/error_utils.hpp"
|
||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
namespace repertory::curl::requests {
|
namespace repertory::curl::requests {
|
||||||
auto http_put_file::set_method(CURL *curl,
|
auto http_put_file::set_method(CURL *curl, stop_type &stop_requested) const
|
||||||
stop_type &stop_requested) const -> bool {
|
-> bool {
|
||||||
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
|
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
|
||||||
|
curl_easy_setopt(curl, CURLOPT_INFILE, nullptr);
|
||||||
|
|
||||||
if (source_path.empty()) {
|
if (source_path.empty()) {
|
||||||
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, 0L);
|
curl_easy_setopt(curl, CURLOPT_INFILESIZE, 0L);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,14 +52,28 @@ auto http_put_file::set_method(CURL *curl,
|
|||||||
utils::file::file::open_or_create_file(source_path),
|
utils::file::file::open_or_create_file(source_path),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (not *read_info->file) {
|
if (not*read_info->file) {
|
||||||
|
utils::error::raise_url_error(function_name, get_path(), source_path,
|
||||||
|
std::runtime_error("failed to open file"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto file_size = read_info->file->size();
|
auto opt_size = read_info->file->size();
|
||||||
|
if (not opt_size.has_value()) {
|
||||||
|
utils::error::raise_url_error(
|
||||||
|
function_name, get_path(), source_path,
|
||||||
|
std::runtime_error("failed to get file size"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto file_size = opt_size.value();
|
||||||
|
if (file_size == 0U) {
|
||||||
|
curl_easy_setopt(curl, CURLOPT_INFILESIZE, 0L);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_READDATA, read_info.get());
|
curl_easy_setopt(curl, CURLOPT_READDATA, read_info.get());
|
||||||
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_file_data);
|
curl_easy_setopt(curl, CURLOPT_READFUNCTION, curl_file_reader);
|
||||||
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, file_size);
|
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, file_size);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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 "comm/curl/requests/http_request_base.hpp"
|
||||||
|
|
||||||
|
#include "utils/file.hpp"
|
||||||
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
|
namespace repertory::curl::requests {
|
||||||
|
auto curl_file_reader(char *buffer, size_t size, size_t nitems, void *instream)
|
||||||
|
-> size_t {
|
||||||
|
auto *read_info = reinterpret_cast<read_file_info *>(instream);
|
||||||
|
|
||||||
|
std::size_t bytes_read{};
|
||||||
|
auto ret =
|
||||||
|
read_info->file->read(reinterpret_cast<unsigned char *>(buffer),
|
||||||
|
size * nitems, read_info->offset, &bytes_read);
|
||||||
|
if (ret) {
|
||||||
|
read_info->offset += bytes_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret && not read_info->stop_requested ? bytes_read
|
||||||
|
: CURL_READFUNC_ABORT;
|
||||||
|
}
|
||||||
|
} // namespace repertory::curl::requests
|
@ -30,7 +30,7 @@ namespace repertory {
|
|||||||
void client_pool::pool::execute(
|
void client_pool::pool::execute(
|
||||||
std::uint64_t thread_id, const worker_callback &worker,
|
std::uint64_t thread_id, const worker_callback &worker,
|
||||||
const worker_complete_callback &worker_complete) {
|
const worker_complete_callback &worker_complete) {
|
||||||
const auto index = thread_id % pool_queues_.size();
|
auto index = thread_id % pool_queues_.size();
|
||||||
auto job = std::make_shared<work_item>(worker, worker_complete);
|
auto job = std::make_shared<work_item>(worker, worker_complete);
|
||||||
auto &pool_queue = pool_queues_[index];
|
auto &pool_queue = pool_queues_[index];
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ client_pool::pool::pool(std::uint8_t pool_size) {
|
|||||||
|
|
||||||
for (std::size_t i = 0U; i < pool_queues_.size(); i++) {
|
for (std::size_t i = 0U; i < pool_queues_.size(); i++) {
|
||||||
pool_threads_.emplace_back([this]() {
|
pool_threads_.emplace_back([this]() {
|
||||||
const auto thread_index = thread_index_++;
|
auto thread_index = thread_index_++;
|
||||||
|
|
||||||
auto &pool_queue = pool_queues_[thread_index];
|
auto &pool_queue = pool_queues_[thread_index];
|
||||||
auto &queue = pool_queue->queue;
|
auto &queue = pool_queue->queue;
|
||||||
@ -74,7 +74,7 @@ client_pool::pool::pool(std::uint8_t pool_size) {
|
|||||||
queue_lock.unlock();
|
queue_lock.unlock();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const auto result = item->work();
|
auto result = item->work();
|
||||||
item->work_complete(result);
|
item->work_complete(result);
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
item->work_complete(utils::from_api_error(api_error::error));
|
item->work_complete(utils::from_api_error(api_error::error));
|
||||||
|
@ -36,8 +36,8 @@ void packet::clear() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto packet::decode(std::string &data) -> packet::error_type {
|
auto packet::decode(std::string &data) -> packet::error_type {
|
||||||
const auto *str = reinterpret_cast<const char *>(&buffer_[decode_offset_]);
|
const auto *str = reinterpret_cast<const char *>(&buffer_.at(decode_offset_));
|
||||||
const auto length = strnlen(str, buffer_.size() - decode_offset_);
|
auto length = strnlen(str, buffer_.size() - decode_offset_);
|
||||||
data = std::string(str, length);
|
data = std::string(str, length);
|
||||||
decode_offset_ += (length + 1);
|
decode_offset_ += (length + 1);
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ auto packet::decode(std::string &data) -> packet::error_type {
|
|||||||
|
|
||||||
auto packet::decode(std::wstring &data) -> packet::error_type {
|
auto packet::decode(std::wstring &data) -> packet::error_type {
|
||||||
std::string utf8_string;
|
std::string utf8_string;
|
||||||
const auto ret = decode(utf8_string);
|
auto ret = decode(utf8_string);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
data = utils::string::from_utf8(utf8_string);
|
data = utils::string::from_utf8(utf8_string);
|
||||||
}
|
}
|
||||||
@ -60,7 +60,7 @@ auto packet::decode(void *&ptr) -> packet::error_type {
|
|||||||
|
|
||||||
auto packet::decode(void *buffer, std::size_t size) -> packet::error_type {
|
auto packet::decode(void *buffer, std::size_t size) -> packet::error_type {
|
||||||
if (size != 0U) {
|
if (size != 0U) {
|
||||||
const auto read_size =
|
auto read_size =
|
||||||
utils::calculate_read_size(buffer_.size(), size, decode_offset_);
|
utils::calculate_read_size(buffer_.size(), size, decode_offset_);
|
||||||
if (read_size == size) {
|
if (read_size == size) {
|
||||||
memcpy(buffer, &buffer_[decode_offset_], size);
|
memcpy(buffer, &buffer_[decode_offset_], size);
|
||||||
@ -76,7 +76,7 @@ auto packet::decode(void *buffer, std::size_t size) -> packet::error_type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto packet::decode(std::int8_t &val) -> packet::error_type {
|
auto packet::decode(std::int8_t &val) -> packet::error_type {
|
||||||
const auto ret = decode(&val, sizeof(val));
|
auto ret = decode(&val, sizeof(val));
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
boost::endian::big_to_native_inplace(val);
|
boost::endian::big_to_native_inplace(val);
|
||||||
}
|
}
|
||||||
@ -84,7 +84,7 @@ auto packet::decode(std::int8_t &val) -> packet::error_type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto packet::decode(std::uint8_t &val) -> packet::error_type {
|
auto packet::decode(std::uint8_t &val) -> packet::error_type {
|
||||||
const auto ret = decode(&val, sizeof(val));
|
auto ret = decode(&val, sizeof(val));
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
boost::endian::big_to_native_inplace(val);
|
boost::endian::big_to_native_inplace(val);
|
||||||
}
|
}
|
||||||
@ -92,7 +92,7 @@ auto packet::decode(std::uint8_t &val) -> packet::error_type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto packet::decode(std::int16_t &val) -> packet::error_type {
|
auto packet::decode(std::int16_t &val) -> packet::error_type {
|
||||||
const auto ret = decode(&val, sizeof(val));
|
auto ret = decode(&val, sizeof(val));
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
boost::endian::big_to_native_inplace(val);
|
boost::endian::big_to_native_inplace(val);
|
||||||
}
|
}
|
||||||
@ -100,7 +100,7 @@ auto packet::decode(std::int16_t &val) -> packet::error_type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto packet::decode(std::uint16_t &val) -> packet::error_type {
|
auto packet::decode(std::uint16_t &val) -> packet::error_type {
|
||||||
const auto ret = decode(&val, sizeof(val));
|
auto ret = decode(&val, sizeof(val));
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
boost::endian::big_to_native_inplace(val);
|
boost::endian::big_to_native_inplace(val);
|
||||||
}
|
}
|
||||||
@ -108,7 +108,7 @@ auto packet::decode(std::uint16_t &val) -> packet::error_type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto packet::decode(std::int32_t &val) -> packet::error_type {
|
auto packet::decode(std::int32_t &val) -> packet::error_type {
|
||||||
const auto ret = decode(&val, sizeof(val));
|
auto ret = decode(&val, sizeof(val));
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
boost::endian::big_to_native_inplace(val);
|
boost::endian::big_to_native_inplace(val);
|
||||||
}
|
}
|
||||||
@ -116,7 +116,7 @@ auto packet::decode(std::int32_t &val) -> packet::error_type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto packet::decode(std::uint32_t &val) -> packet::error_type {
|
auto packet::decode(std::uint32_t &val) -> packet::error_type {
|
||||||
const auto ret = decode(&val, sizeof(val));
|
auto ret = decode(&val, sizeof(val));
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
boost::endian::big_to_native_inplace(val);
|
boost::endian::big_to_native_inplace(val);
|
||||||
}
|
}
|
||||||
@ -124,7 +124,7 @@ auto packet::decode(std::uint32_t &val) -> packet::error_type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto packet::decode(std::int64_t &val) -> packet::error_type {
|
auto packet::decode(std::int64_t &val) -> packet::error_type {
|
||||||
const auto ret = decode(&val, sizeof(val));
|
auto ret = decode(&val, sizeof(val));
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
boost::endian::big_to_native_inplace(val);
|
boost::endian::big_to_native_inplace(val);
|
||||||
}
|
}
|
||||||
@ -132,7 +132,7 @@ auto packet::decode(std::int64_t &val) -> packet::error_type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto packet::decode(std::uint64_t &val) -> packet::error_type {
|
auto packet::decode(std::uint64_t &val) -> packet::error_type {
|
||||||
const auto ret = decode(&val, sizeof(val));
|
auto ret = decode(&val, sizeof(val));
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
boost::endian::big_to_native_inplace(val);
|
boost::endian::big_to_native_inplace(val);
|
||||||
}
|
}
|
||||||
@ -140,7 +140,7 @@ auto packet::decode(std::uint64_t &val) -> packet::error_type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto packet::decode(remote::setattr_x &val) -> packet::error_type {
|
auto packet::decode(remote::setattr_x &val) -> packet::error_type {
|
||||||
const auto ret = decode(&val, sizeof(val));
|
auto ret = decode(&val, sizeof(val));
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
boost::endian::big_to_native_inplace(val.acctime);
|
boost::endian::big_to_native_inplace(val.acctime);
|
||||||
boost::endian::big_to_native_inplace(val.bkuptime);
|
boost::endian::big_to_native_inplace(val.bkuptime);
|
||||||
@ -159,7 +159,7 @@ auto packet::decode(remote::setattr_x &val) -> packet::error_type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto packet::decode(remote::stat &val) -> packet::error_type {
|
auto packet::decode(remote::stat &val) -> packet::error_type {
|
||||||
const auto ret = decode(&val, sizeof(val));
|
auto ret = decode(&val, sizeof(val));
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
boost::endian::big_to_native_inplace(val.st_mode);
|
boost::endian::big_to_native_inplace(val.st_mode);
|
||||||
boost::endian::big_to_native_inplace(val.st_nlink);
|
boost::endian::big_to_native_inplace(val.st_nlink);
|
||||||
@ -179,7 +179,7 @@ auto packet::decode(remote::stat &val) -> packet::error_type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto packet::decode(remote::statfs &val) -> packet::error_type {
|
auto packet::decode(remote::statfs &val) -> packet::error_type {
|
||||||
const auto ret = decode(&val, sizeof(val));
|
auto ret = decode(&val, sizeof(val));
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
boost::endian::big_to_native_inplace(val.f_bavail);
|
boost::endian::big_to_native_inplace(val.f_bavail);
|
||||||
boost::endian::big_to_native_inplace(val.f_bfree);
|
boost::endian::big_to_native_inplace(val.f_bfree);
|
||||||
@ -200,7 +200,7 @@ auto packet::decode(remote::statfs_x &val) -> packet::error_type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto packet::decode(remote::file_info &val) -> packet::error_type {
|
auto packet::decode(remote::file_info &val) -> packet::error_type {
|
||||||
const auto ret = decode(&val, sizeof(val));
|
auto ret = decode(&val, sizeof(val));
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
boost::endian::big_to_native_inplace(val.AllocationSize);
|
boost::endian::big_to_native_inplace(val.AllocationSize);
|
||||||
boost::endian::big_to_native_inplace(val.ChangeTime);
|
boost::endian::big_to_native_inplace(val.ChangeTime);
|
||||||
@ -268,7 +268,7 @@ void packet::encode(const void *buffer, std::size_t size, bool should_reserve) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void packet::encode(std::string_view str) {
|
void packet::encode(std::string_view str) {
|
||||||
const auto len = str.size();
|
auto len = str.size();
|
||||||
buffer_.reserve(len + 1 + buffer_.size());
|
buffer_.reserve(len + 1 + buffer_.size());
|
||||||
encode(str.data(), len, false);
|
encode(str.data(), len, false);
|
||||||
buffer_.emplace_back(0);
|
buffer_.emplace_back(0);
|
||||||
@ -401,7 +401,7 @@ void packet::encode_top(const void *buffer, std::size_t size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void packet::encode_top(std::string_view str) {
|
void packet::encode_top(std::string_view str) {
|
||||||
const auto len = str.size();
|
auto len = str.size();
|
||||||
buffer_.reserve(len + 1U + buffer_.size());
|
buffer_.reserve(len + 1U + buffer_.size());
|
||||||
encode_top(str.data(), len, false);
|
encode_top(str.data(), len, false);
|
||||||
buffer_.insert(buffer_.begin() + static_cast<std::int32_t>(len), 0);
|
buffer_.insert(buffer_.begin() + static_cast<std::int32_t>(len), 0);
|
||||||
@ -531,7 +531,7 @@ void packet::encrypt(std::string_view token) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void packet::transfer_into(data_buffer &buffer) {
|
void packet::to_buffer(data_buffer &buffer) {
|
||||||
buffer = std::move(buffer_);
|
buffer = std::move(buffer_);
|
||||||
buffer_ = data_buffer();
|
buffer_ = data_buffer();
|
||||||
decode_offset_ = 0;
|
decode_offset_ = 0;
|
||||||
|
@ -38,18 +38,8 @@ E_SIMPLE2(packet_client_timeout, error, true,
|
|||||||
);
|
);
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
packet_client::packet_client(std::string host_name_or_ip,
|
packet_client::packet_client(remote::remote_config cfg)
|
||||||
std::uint8_t max_connections, std::uint16_t port,
|
: cfg_(std::move(cfg)), unique_id_(utils::create_uuid_string()) {}
|
||||||
std::uint16_t receive_timeout,
|
|
||||||
std::uint16_t send_timeout,
|
|
||||||
std::string encryption_token)
|
|
||||||
: host_name_or_ip_(std::move(host_name_or_ip)),
|
|
||||||
max_connections_(max_connections == 0U ? 20U : max_connections),
|
|
||||||
port_(port),
|
|
||||||
receive_timeout_(receive_timeout),
|
|
||||||
send_timeout_(send_timeout),
|
|
||||||
encryption_token_(std::move(encryption_token)),
|
|
||||||
unique_id_(utils::create_uuid_string()) {}
|
|
||||||
|
|
||||||
packet_client::~packet_client() {
|
packet_client::~packet_client() {
|
||||||
allow_connections_ = false;
|
allow_connections_ = false;
|
||||||
@ -85,7 +75,7 @@ void packet_client::connect(client &cli) {
|
|||||||
cli.socket.set_option(boost::asio::socket_base::linger(false, 0));
|
cli.socket.set_option(boost::asio::socket_base::linger(false, 0));
|
||||||
|
|
||||||
packet response;
|
packet response;
|
||||||
const auto res = read_packet(cli, response);
|
auto res = read_packet(cli, response);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
throw std::runtime_error(std::to_string(res));
|
throw std::runtime_error(std::to_string(res));
|
||||||
}
|
}
|
||||||
@ -95,27 +85,27 @@ void packet_client::connect(client &cli) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto packet_client::get_client() -> std::shared_ptr<packet_client::client> {
|
auto packet_client::get_client() -> std::shared_ptr<packet_client::client> {
|
||||||
std::shared_ptr<client> ret;
|
|
||||||
|
|
||||||
unique_mutex_lock clients_lock(clients_mutex_);
|
unique_mutex_lock clients_lock(clients_mutex_);
|
||||||
if (allow_connections_) {
|
if (not allow_connections_) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (clients_.empty()) {
|
if (clients_.empty()) {
|
||||||
clients_lock.unlock();
|
clients_lock.unlock();
|
||||||
ret = std::make_shared<client>(io_context_);
|
|
||||||
connect(*ret);
|
auto cli = std::make_shared<client>(io_context_);
|
||||||
} else {
|
connect(*cli);
|
||||||
ret = clients_[0U];
|
return cli;
|
||||||
utils::collection::remove_element(clients_, ret);
|
|
||||||
clients_lock.unlock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
auto cli = clients_.at(0U);
|
||||||
|
utils::collection::remove_element(clients_, cli);
|
||||||
|
return cli;
|
||||||
}
|
}
|
||||||
|
|
||||||
void packet_client::put_client(std::shared_ptr<client> &cli) {
|
void packet_client::put_client(std::shared_ptr<client> &cli) {
|
||||||
mutex_lock clientsLock(clients_mutex_);
|
mutex_lock clientsLock(clients_mutex_);
|
||||||
if (clients_.size() < max_connections_) {
|
if (clients_.size() < cfg_.max_connections) {
|
||||||
clients_.emplace_back(cli);
|
clients_.emplace_back(cli);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,7 +116,7 @@ auto packet_client::read_packet(client &cli, packet &response)
|
|||||||
const auto read_buffer = [&]() {
|
const auto read_buffer = [&]() {
|
||||||
std::uint32_t offset{};
|
std::uint32_t offset{};
|
||||||
while (offset < buffer.size()) {
|
while (offset < buffer.size()) {
|
||||||
const auto bytes_read = boost::asio::read(
|
auto bytes_read = boost::asio::read(
|
||||||
cli.socket,
|
cli.socket,
|
||||||
boost::asio::buffer(&buffer[offset], buffer.size() - offset));
|
boost::asio::buffer(&buffer[offset], buffer.size() - offset));
|
||||||
if (bytes_read <= 0) {
|
if (bytes_read <= 0) {
|
||||||
@ -137,14 +127,14 @@ auto packet_client::read_packet(client &cli, packet &response)
|
|||||||
};
|
};
|
||||||
read_buffer();
|
read_buffer();
|
||||||
|
|
||||||
const auto size = boost::endian::big_to_native(
|
auto size = boost::endian::big_to_native(
|
||||||
*reinterpret_cast<std::uint32_t *>(buffer.data()));
|
*reinterpret_cast<std::uint32_t *>(buffer.data()));
|
||||||
buffer.resize(size);
|
buffer.resize(size);
|
||||||
|
|
||||||
read_buffer();
|
read_buffer();
|
||||||
response = std::move(buffer);
|
response = std::move(buffer);
|
||||||
|
|
||||||
auto ret = response.decrypt(encryption_token_);
|
auto ret = response.decrypt(cfg_.encryption_token);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
ret = response.decode(cli.nonce);
|
ret = response.decode(cli.nonce);
|
||||||
}
|
}
|
||||||
@ -153,10 +143,13 @@ auto packet_client::read_packet(client &cli, packet &response)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void packet_client::resolve() {
|
void packet_client::resolve() {
|
||||||
if (resolve_results_.empty()) {
|
if (not resolve_results_.empty()) {
|
||||||
resolve_results_ = tcp::resolver(io_context_)
|
return;
|
||||||
.resolve({host_name_or_ip_, std::to_string(port_)});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resolve_results_ =
|
||||||
|
tcp::resolver(io_context_)
|
||||||
|
.resolve(cfg_.host_name_or_ip, std::to_string(cfg_.api_port));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto packet_client::send(std::string_view method, std::uint32_t &service_flags)
|
auto packet_client::send(std::string_view method, std::uint32_t &service_flags)
|
||||||
@ -184,14 +177,14 @@ auto packet_client::send(std::string_view method, packet &request,
|
|||||||
request.encode_top(PACKET_SERVICE_FLAGS);
|
request.encode_top(PACKET_SERVICE_FLAGS);
|
||||||
request.encode_top(std::string{project_get_version()});
|
request.encode_top(std::string{project_get_version()});
|
||||||
|
|
||||||
static const std::uint8_t max_attempts{5U};
|
static constexpr const std::uint8_t max_attempts{5U};
|
||||||
for (std::uint8_t i = 1U;
|
for (std::uint8_t i = 1U;
|
||||||
allow_connections_ && not success && (i <= max_attempts); i++) {
|
allow_connections_ && not success && (i <= max_attempts); i++) {
|
||||||
auto current_client = get_client();
|
auto current_client = get_client();
|
||||||
if (current_client) {
|
if (current_client) {
|
||||||
try {
|
try {
|
||||||
request.encode_top(current_client->nonce);
|
request.encode_top(current_client->nonce);
|
||||||
request.encrypt(encryption_token_);
|
request.encrypt(cfg_.encryption_token);
|
||||||
|
|
||||||
timeout request_timeout(
|
timeout request_timeout(
|
||||||
[method, current_client]() {
|
[method, current_client]() {
|
||||||
@ -199,11 +192,11 @@ auto packet_client::send(std::string_view method, packet &request,
|
|||||||
"request", std::string{method});
|
"request", std::string{method});
|
||||||
packet_client::close(*current_client);
|
packet_client::close(*current_client);
|
||||||
},
|
},
|
||||||
std::chrono::seconds(send_timeout_));
|
std::chrono::milliseconds(cfg_.send_timeout_ms));
|
||||||
|
|
||||||
std::uint32_t offset{};
|
std::uint32_t offset{};
|
||||||
while (offset < request.get_size()) {
|
while (offset < request.get_size()) {
|
||||||
const auto bytes_written = boost::asio::write(
|
auto bytes_written = boost::asio::write(
|
||||||
current_client->socket,
|
current_client->socket,
|
||||||
boost::asio::buffer(&request[offset],
|
boost::asio::buffer(&request[offset],
|
||||||
request.get_size() - offset));
|
request.get_size() - offset));
|
||||||
@ -221,7 +214,7 @@ auto packet_client::send(std::string_view method, packet &request,
|
|||||||
"response", std::string{method});
|
"response", std::string{method});
|
||||||
packet_client::close(*current_client);
|
packet_client::close(*current_client);
|
||||||
},
|
},
|
||||||
std::chrono::seconds(receive_timeout_));
|
std::chrono::milliseconds(cfg_.recv_timeout_ms));
|
||||||
|
|
||||||
ret = read_packet(*current_client, response);
|
ret = read_packet(*current_client, response);
|
||||||
response_timeout.disable();
|
response_timeout.disable();
|
||||||
|
@ -68,11 +68,11 @@ void packet_server::add_client(connection &conn, const std::string &client_id) {
|
|||||||
void packet_server::initialize(const uint16_t &port, uint8_t pool_size) {
|
void packet_server::initialize(const uint16_t &port, uint8_t pool_size) {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
pool_size = std::max(uint8_t(1U), pool_size);
|
pool_size = std::max(std::uint8_t(1U), pool_size);
|
||||||
server_thread_ = std::make_unique<std::thread>([this, port, pool_size]() {
|
server_thread_ = std::make_unique<std::thread>([this, port, pool_size]() {
|
||||||
tcp::acceptor acceptor(io_context_);
|
tcp::acceptor acceptor(io_context_);
|
||||||
try {
|
try {
|
||||||
const auto endpoint = tcp::endpoint(tcp::v4(), port);
|
auto endpoint = tcp::endpoint(tcp::v4(), port);
|
||||||
acceptor.open(endpoint.protocol());
|
acceptor.open(endpoint.protocol());
|
||||||
acceptor.set_option(socket_base::reuse_address(true));
|
acceptor.set_option(socket_base::reuse_address(true));
|
||||||
acceptor.bind(endpoint);
|
acceptor.bind(endpoint);
|
||||||
@ -148,7 +148,7 @@ void packet_server::read_packet(std::shared_ptr<connection> conn,
|
|||||||
const auto read_buffer = [&]() {
|
const auto read_buffer = [&]() {
|
||||||
std::uint32_t offset{};
|
std::uint32_t offset{};
|
||||||
while (offset < conn->buffer.size()) {
|
while (offset < conn->buffer.size()) {
|
||||||
const auto bytes_read = boost::asio::read(
|
auto bytes_read = boost::asio::read(
|
||||||
conn->socket, boost::asio::buffer(&conn->buffer[offset],
|
conn->socket, boost::asio::buffer(&conn->buffer[offset],
|
||||||
conn->buffer.size() - offset));
|
conn->buffer.size() - offset));
|
||||||
if (bytes_read <= 0) {
|
if (bytes_read <= 0) {
|
||||||
@ -244,7 +244,7 @@ void packet_server::send_response(std::shared_ptr<connection> conn,
|
|||||||
response.encode_top(PACKET_SERVICE_FLAGS);
|
response.encode_top(PACKET_SERVICE_FLAGS);
|
||||||
response.encode_top(conn->nonce);
|
response.encode_top(conn->nonce);
|
||||||
response.encrypt(encryption_token_);
|
response.encrypt(encryption_token_);
|
||||||
response.transfer_into(conn->buffer);
|
response.to_buffer(conn->buffer);
|
||||||
|
|
||||||
boost::asio::async_write(
|
boost::asio::async_write(
|
||||||
conn->socket, boost::asio::buffer(conn->buffer),
|
conn->socket, boost::asio::buffer(conn->buffer),
|
||||||
|
38
repertory/librepertory/src/db/file_db.cpp
Normal file
38
repertory/librepertory/src/db/file_db.cpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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 "db/file_db.hpp"
|
||||||
|
|
||||||
|
#include "app_config.hpp"
|
||||||
|
#include "db/impl/rdb_file_db.hpp"
|
||||||
|
#include "db/impl/sqlite_file_db.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
auto create_file_db(const app_config &cfg) -> std::unique_ptr<i_file_db> {
|
||||||
|
switch (cfg.get_database_type()) {
|
||||||
|
case database_type::sqlite:
|
||||||
|
return std::make_unique<sqlite_file_db>(cfg);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return std::make_unique<rdb_file_db>(cfg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace repertory
|
40
repertory/librepertory/src/db/file_mgr_db.cpp
Normal file
40
repertory/librepertory/src/db/file_mgr_db.cpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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 "db/file_mgr_db.hpp"
|
||||||
|
|
||||||
|
#include "app_config.hpp"
|
||||||
|
#include "db/i_file_mgr_db.hpp"
|
||||||
|
#include "db/impl/rdb_file_mgr_db.hpp"
|
||||||
|
#include "db/impl/sqlite_file_mgr_db.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
auto create_file_mgr_db(const app_config &cfg)
|
||||||
|
-> std::unique_ptr<i_file_mgr_db> {
|
||||||
|
switch (cfg.get_database_type()) {
|
||||||
|
case database_type::sqlite:
|
||||||
|
return std::make_unique<sqlite_file_mgr_db>(cfg);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return std::make_unique<rdb_file_mgr_db>(cfg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace repertory
|
390
repertory/librepertory/src/db/impl/rdb_file_db.cpp
Normal file
390
repertory/librepertory/src/db/impl/rdb_file_db.cpp
Normal file
@ -0,0 +1,390 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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 "db/impl/rdb_file_db.hpp"
|
||||||
|
|
||||||
|
#include "app_config.hpp"
|
||||||
|
#include "types/startup_exception.hpp"
|
||||||
|
#include "utils/config.hpp"
|
||||||
|
#include "utils/error_utils.hpp"
|
||||||
|
#include "utils/file.hpp"
|
||||||
|
#include "utils/path.hpp"
|
||||||
|
#include "utils/string.hpp"
|
||||||
|
#include "utils/utils.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
rdb_file_db::rdb_file_db(const app_config &cfg) : cfg_(cfg) {
|
||||||
|
create_or_open(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
rdb_file_db::~rdb_file_db() { db_.reset(); }
|
||||||
|
|
||||||
|
void rdb_file_db::create_or_open(bool clear) {
|
||||||
|
db_.reset();
|
||||||
|
|
||||||
|
auto families = std::vector<rocksdb::ColumnFamilyDescriptor>();
|
||||||
|
families.emplace_back(rocksdb::kDefaultColumnFamilyName,
|
||||||
|
rocksdb::ColumnFamilyOptions());
|
||||||
|
families.emplace_back("file", rocksdb::ColumnFamilyOptions());
|
||||||
|
families.emplace_back("path", rocksdb::ColumnFamilyOptions());
|
||||||
|
families.emplace_back("source", rocksdb::ColumnFamilyOptions());
|
||||||
|
|
||||||
|
auto handles = std::vector<rocksdb::ColumnFamilyHandle *>();
|
||||||
|
db_ = utils::create_rocksdb(cfg_, "file", families, handles, clear);
|
||||||
|
|
||||||
|
std::size_t idx{};
|
||||||
|
directory_family_ = handles.at(idx++);
|
||||||
|
file_family_ = handles.at(idx++);
|
||||||
|
path_family_ = handles.at(idx++);
|
||||||
|
source_family_ = handles.at(idx++);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_db::add_directory(const std::string &api_path,
|
||||||
|
const std::string &source_path) -> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
std::string existing_source_path;
|
||||||
|
auto result = get_directory_source_path(api_path, existing_source_path);
|
||||||
|
if (result != api_error::success &&
|
||||||
|
result != api_error::directory_not_found) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return perform_action(
|
||||||
|
function_name, [&](rocksdb::Transaction *txn) -> rocksdb::Status {
|
||||||
|
if (not existing_source_path.empty()) {
|
||||||
|
auto res = remove_item(api_path, existing_source_path, txn);
|
||||||
|
if (not res.ok() && not res.IsNotFound()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto res = txn->Put(directory_family_, api_path, source_path);
|
||||||
|
if (not res.ok()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = txn->Put(path_family_, api_path, source_path);
|
||||||
|
if (not res.ok()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return txn->Put(source_family_, source_path, api_path);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_db::add_or_update_file(const i_file_db::file_data &data)
|
||||||
|
-> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
std::string existing_source_path;
|
||||||
|
auto result = get_file_source_path(data.api_path, existing_source_path);
|
||||||
|
if (result != api_error::success && result != api_error::item_not_found) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return perform_action(
|
||||||
|
function_name, [&](rocksdb::Transaction *txn) -> rocksdb::Status {
|
||||||
|
if (not existing_source_path.empty()) {
|
||||||
|
auto res = remove_item(data.api_path, existing_source_path, txn);
|
||||||
|
if (not res.ok() && not res.IsNotFound()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
json json_data = {
|
||||||
|
{"file_size", data.file_size},
|
||||||
|
{"iv", data.iv_list},
|
||||||
|
{"source_path", data.source_path},
|
||||||
|
};
|
||||||
|
|
||||||
|
auto res = txn->Put(file_family_, data.api_path, json_data.dump());
|
||||||
|
if (not res.ok()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = txn->Put(path_family_, data.api_path, data.source_path);
|
||||||
|
if (not res.ok()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return txn->Put(source_family_, data.source_path, data.api_path);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void rdb_file_db::clear() { create_or_open(true); }
|
||||||
|
|
||||||
|
auto rdb_file_db::create_iterator(rocksdb::ColumnFamilyHandle *family) const
|
||||||
|
-> std::shared_ptr<rocksdb::Iterator> {
|
||||||
|
return std::shared_ptr<rocksdb::Iterator>(
|
||||||
|
db_->NewIterator(rocksdb::ReadOptions{}, family));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_db::count() const -> std::uint64_t {
|
||||||
|
std::uint64_t ret{};
|
||||||
|
|
||||||
|
auto iter = create_iterator(source_family_);
|
||||||
|
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
||||||
|
++ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_db::get_api_path(const std::string &source_path,
|
||||||
|
std::string &api_path) const -> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
return perform_action(function_name, [&]() -> rocksdb::Status {
|
||||||
|
return db_->Get(rocksdb::ReadOptions{}, source_family_, source_path,
|
||||||
|
&api_path);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_db::get_directory_api_path(
|
||||||
|
const std::string &source_path, std::string &api_path) const -> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
auto result = perform_action(function_name, [&]() -> rocksdb::Status {
|
||||||
|
auto res = db_->Get(rocksdb::ReadOptions{}, source_family_, source_path,
|
||||||
|
&api_path);
|
||||||
|
if (not res.ok()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value;
|
||||||
|
return db_->Get(rocksdb::ReadOptions{}, directory_family_, api_path,
|
||||||
|
&value);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result != api_error::success) {
|
||||||
|
api_path.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result == api_error::item_not_found ? api_error::directory_not_found
|
||||||
|
: result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_db::get_directory_source_path(
|
||||||
|
const std::string &api_path, std::string &source_path) const -> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
auto result = perform_action(function_name, [&]() -> rocksdb::Status {
|
||||||
|
return db_->Get(rocksdb::ReadOptions{}, directory_family_, api_path,
|
||||||
|
&source_path);
|
||||||
|
});
|
||||||
|
|
||||||
|
return result == api_error::item_not_found ? api_error::directory_not_found
|
||||||
|
: result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_db::get_file_api_path(const std::string &source_path,
|
||||||
|
std::string &api_path) const -> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
auto result = perform_action(function_name, [&]() -> rocksdb::Status {
|
||||||
|
auto res = db_->Get(rocksdb::ReadOptions{}, source_family_, source_path,
|
||||||
|
&api_path);
|
||||||
|
if (not res.ok()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string value;
|
||||||
|
return db_->Get(rocksdb::ReadOptions{}, file_family_, api_path, &value);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result != api_error::success) {
|
||||||
|
api_path.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_db::get_file_data(const std::string &api_path,
|
||||||
|
i_file_db::file_data &data) const -> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
auto result = perform_action(function_name, [&]() -> rocksdb::Status {
|
||||||
|
std::string value;
|
||||||
|
auto res = db_->Get(rocksdb::ReadOptions{}, file_family_, api_path, &value);
|
||||||
|
if (not res.ok()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto json_data = json::parse(value);
|
||||||
|
data.api_path = api_path;
|
||||||
|
data.file_size = json_data.at("file_size").get<std::uint64_t>();
|
||||||
|
data.iv_list =
|
||||||
|
json_data.at("iv")
|
||||||
|
.get<std::vector<
|
||||||
|
std::array<unsigned char,
|
||||||
|
crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>>();
|
||||||
|
data.source_path = json_data.at("source_path").get<std::string>();
|
||||||
|
|
||||||
|
return res;
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_db::get_file_source_path(
|
||||||
|
const std::string &api_path, std::string &source_path) const -> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
auto result = perform_action(function_name, [&]() -> rocksdb::Status {
|
||||||
|
std::string value;
|
||||||
|
auto res = db_->Get(rocksdb::ReadOptions{}, file_family_, api_path, &value);
|
||||||
|
if (not res.ok()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto json_data = json::parse(value);
|
||||||
|
source_path = json_data.at("source_path").get<std::string>();
|
||||||
|
return res;
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_db::get_item_list() const -> std::vector<i_file_db::file_info> {
|
||||||
|
std::vector<i_file_db::file_info> ret{};
|
||||||
|
{
|
||||||
|
auto iter = create_iterator(directory_family_);
|
||||||
|
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
||||||
|
ret.emplace_back(i_file_db::file_info{
|
||||||
|
iter->key().ToString(),
|
||||||
|
true,
|
||||||
|
iter->value().ToString(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto iter = create_iterator(file_family_);
|
||||||
|
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
||||||
|
auto json_data = json::parse(iter->value().ToString());
|
||||||
|
ret.emplace_back(i_file_db::file_info{
|
||||||
|
iter->key().ToString(),
|
||||||
|
true,
|
||||||
|
json_data.at("source_path").get<std::string>(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_db::get_source_path(const std::string &api_path,
|
||||||
|
std::string &source_path) const -> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
return perform_action(function_name, [&]() -> rocksdb::Status {
|
||||||
|
return db_->Get(rocksdb::ReadOptions{}, path_family_, api_path,
|
||||||
|
&source_path);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_db::perform_action(std::string_view function_name,
|
||||||
|
std::function<rocksdb::Status()> action)
|
||||||
|
-> api_error {
|
||||||
|
auto res = action();
|
||||||
|
if (res.ok()) {
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not res.IsNotFound()) {
|
||||||
|
utils::error::raise_error(function_name, res.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.IsNotFound() ? api_error::item_not_found : api_error::error;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_db::perform_action(
|
||||||
|
std::string_view function_name,
|
||||||
|
std::function<rocksdb::Status(rocksdb::Transaction *txn)> action)
|
||||||
|
-> api_error {
|
||||||
|
std::unique_ptr<rocksdb::Transaction> txn{
|
||||||
|
db_->BeginTransaction(rocksdb::WriteOptions{},
|
||||||
|
rocksdb::TransactionOptions{}),
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto res = action(txn.get());
|
||||||
|
if (res.ok()) {
|
||||||
|
auto commit_res = txn->Commit();
|
||||||
|
if (commit_res.ok()) {
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::error::raise_error(function_name,
|
||||||
|
"rocksdb commit failed|" + res.ToString());
|
||||||
|
return api_error::error;
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::error::raise_error(function_name,
|
||||||
|
"rocksdb action failed|" + res.ToString());
|
||||||
|
} catch (const std::exception &ex) {
|
||||||
|
utils::error::raise_error(function_name, ex,
|
||||||
|
"failed to handle rocksdb action");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rollback_res = txn->Rollback();
|
||||||
|
utils::error::raise_error(function_name, "rocksdb rollback failed|" +
|
||||||
|
rollback_res.ToString());
|
||||||
|
return api_error::error;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_db::remove_item(const std::string &api_path) -> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
std::string source_path;
|
||||||
|
auto res = get_source_path(api_path, source_path);
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return perform_action(function_name,
|
||||||
|
[&](rocksdb::Transaction *txn) -> rocksdb::Status {
|
||||||
|
return remove_item(api_path, source_path, txn);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_db::remove_item(const std::string &api_path,
|
||||||
|
const std::string &source_path,
|
||||||
|
rocksdb::Transaction *txn) -> rocksdb::Status {
|
||||||
|
auto res = txn->Delete(source_family_, source_path);
|
||||||
|
if (not res.ok()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = txn->Delete(path_family_, api_path);
|
||||||
|
if (not res.ok()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = txn->Delete(directory_family_, api_path);
|
||||||
|
if (not res.ok()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return txn->Delete(file_family_, api_path);
|
||||||
|
}
|
||||||
|
} // namespace repertory
|
327
repertory/librepertory/src/db/impl/rdb_file_mgr_db.cpp
Normal file
327
repertory/librepertory/src/db/impl/rdb_file_mgr_db.cpp
Normal file
@ -0,0 +1,327 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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 "db/impl/rdb_file_mgr_db.hpp"
|
||||||
|
|
||||||
|
#include "app_config.hpp"
|
||||||
|
#include "types/startup_exception.hpp"
|
||||||
|
#include "utils/config.hpp"
|
||||||
|
#include "utils/error_utils.hpp"
|
||||||
|
#include "utils/file.hpp"
|
||||||
|
#include "utils/path.hpp"
|
||||||
|
#include "utils/string.hpp"
|
||||||
|
#include "utils/utils.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
rdb_file_mgr_db::rdb_file_mgr_db(const app_config &cfg) : cfg_(cfg) {
|
||||||
|
create_or_open(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
rdb_file_mgr_db::~rdb_file_mgr_db() { db_.reset(); }
|
||||||
|
|
||||||
|
void rdb_file_mgr_db::create_or_open(bool clear) {
|
||||||
|
db_.reset();
|
||||||
|
|
||||||
|
auto families = std::vector<rocksdb::ColumnFamilyDescriptor>();
|
||||||
|
families.emplace_back(rocksdb::kDefaultColumnFamilyName,
|
||||||
|
rocksdb::ColumnFamilyOptions());
|
||||||
|
families.emplace_back("upload_active", rocksdb::ColumnFamilyOptions());
|
||||||
|
families.emplace_back("upload", rocksdb::ColumnFamilyOptions());
|
||||||
|
|
||||||
|
auto handles = std::vector<rocksdb::ColumnFamilyHandle *>();
|
||||||
|
db_ = utils::create_rocksdb(cfg_, "file_mgr", families, handles, clear);
|
||||||
|
|
||||||
|
std::size_t idx{};
|
||||||
|
resume_family_ = handles.at(idx++);
|
||||||
|
upload_active_family_ = handles.at(idx++);
|
||||||
|
upload_family_ = handles.at(idx++);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::add_resume(const resume_entry &entry) -> bool {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
return perform_action(
|
||||||
|
function_name,
|
||||||
|
[this, &entry](rocksdb::Transaction *txn) -> rocksdb::Status {
|
||||||
|
return add_resume(entry, txn);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::add_resume(const resume_entry &entry,
|
||||||
|
rocksdb::Transaction *txn) -> rocksdb::Status {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
auto data = json({
|
||||||
|
{"chunk_size", entry.chunk_size},
|
||||||
|
{"read_state", utils::string::from_dynamic_bitset(entry.read_state)},
|
||||||
|
{"source_path", entry.source_path},
|
||||||
|
});
|
||||||
|
return txn->Put(resume_family_, entry.api_path, data.dump());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::add_upload(const upload_entry &entry) -> bool {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
return perform_action(
|
||||||
|
function_name,
|
||||||
|
[this, &entry](rocksdb::Transaction *txn) -> rocksdb::Status {
|
||||||
|
return txn->Put(upload_family_,
|
||||||
|
utils::string::zero_pad(std::to_string(++id_), 20U) +
|
||||||
|
'|' + entry.api_path,
|
||||||
|
entry.source_path);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::add_upload_active(const upload_active_entry &entry)
|
||||||
|
-> bool {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
return perform_action(
|
||||||
|
function_name,
|
||||||
|
[this, &entry](rocksdb::Transaction *txn) -> rocksdb::Status {
|
||||||
|
return txn->Put(upload_active_family_, entry.api_path,
|
||||||
|
entry.source_path);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void rdb_file_mgr_db::clear() { create_or_open(true); }
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::create_iterator(rocksdb::ColumnFamilyHandle *family) const
|
||||||
|
-> std::shared_ptr<rocksdb::Iterator> {
|
||||||
|
return std::shared_ptr<rocksdb::Iterator>(
|
||||||
|
db_->NewIterator(rocksdb::ReadOptions(), family));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::get_next_upload() const -> std::optional<upload_entry> {
|
||||||
|
auto iter = create_iterator(upload_family_);
|
||||||
|
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
||||||
|
auto parts = utils::string::split(iter->key().ToString(), '|', false);
|
||||||
|
parts.erase(parts.begin());
|
||||||
|
|
||||||
|
auto api_path = utils::string::join(parts, '|');
|
||||||
|
|
||||||
|
return upload_entry{
|
||||||
|
api_path,
|
||||||
|
iter->value().ToString(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::get_resume_list() const -> std::vector<resume_entry> {
|
||||||
|
std::vector<resume_entry> ret;
|
||||||
|
|
||||||
|
auto iter = create_iterator(resume_family_);
|
||||||
|
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
||||||
|
auto data = json::parse(iter->value().ToString());
|
||||||
|
ret.emplace_back(resume_entry{
|
||||||
|
iter->key().ToString(),
|
||||||
|
data.at("chunk_size").get<std::uint64_t>(),
|
||||||
|
utils::string::to_dynamic_bitset(
|
||||||
|
data.at("read_state").get<std::string>()),
|
||||||
|
data.at("source_path").get<std::string>(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::get_upload(const std::string &api_path) const
|
||||||
|
-> std::optional<upload_entry> {
|
||||||
|
auto iter = create_iterator(upload_family_);
|
||||||
|
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
||||||
|
auto parts = utils::string::split(iter->key().ToString(), '|', false);
|
||||||
|
parts.erase(parts.begin());
|
||||||
|
|
||||||
|
if (api_path != utils::string::join(parts, '|')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return upload_entry{
|
||||||
|
api_path,
|
||||||
|
iter->value().ToString(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::get_upload_active_list() const
|
||||||
|
-> std::vector<upload_active_entry> {
|
||||||
|
std::vector<upload_active_entry> ret;
|
||||||
|
|
||||||
|
auto iter = create_iterator(upload_active_family_);
|
||||||
|
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
||||||
|
ret.emplace_back(upload_active_entry{
|
||||||
|
iter->key().ToString(),
|
||||||
|
iter->value().ToString(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::perform_action(std::string_view function_name,
|
||||||
|
std::function<rocksdb::Status()> action)
|
||||||
|
-> bool {
|
||||||
|
try {
|
||||||
|
auto res = action();
|
||||||
|
if (not res.ok()) {
|
||||||
|
utils::error::raise_error(function_name, res.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.ok();
|
||||||
|
} catch (const std::exception &ex) {
|
||||||
|
utils::error::raise_error(function_name, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::perform_action(
|
||||||
|
std::string_view function_name,
|
||||||
|
std::function<rocksdb::Status(rocksdb::Transaction *txn)> action) -> bool {
|
||||||
|
std::unique_ptr<rocksdb::Transaction> txn{
|
||||||
|
db_->BeginTransaction(rocksdb::WriteOptions{},
|
||||||
|
rocksdb::TransactionOptions{}),
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto res = action(txn.get());
|
||||||
|
if (res.ok()) {
|
||||||
|
auto commit_res = txn->Commit();
|
||||||
|
if (commit_res.ok()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::error::raise_error(function_name,
|
||||||
|
"rocksdb commit failed|" + res.ToString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::error::raise_error(function_name,
|
||||||
|
"rocksdb action failed|" + res.ToString());
|
||||||
|
} catch (const std::exception &ex) {
|
||||||
|
utils::error::raise_error(function_name, ex,
|
||||||
|
"failed to handle rocksdb action");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rollback_res = txn->Rollback();
|
||||||
|
utils::error::raise_error(function_name, "rocksdb rollback failed|" +
|
||||||
|
rollback_res.ToString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::remove_resume(const std::string &api_path) -> bool {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
return perform_action(
|
||||||
|
function_name,
|
||||||
|
[this, &api_path](rocksdb::Transaction *txn) -> rocksdb::Status {
|
||||||
|
return remove_resume(api_path, txn);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::remove_resume(
|
||||||
|
const std::string &api_path, rocksdb::Transaction *txn) -> rocksdb::Status {
|
||||||
|
return txn->Delete(resume_family_, api_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::remove_upload(const std::string &api_path) -> bool {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
auto iter = create_iterator(upload_family_);
|
||||||
|
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
||||||
|
auto parts = utils::string::split(iter->key().ToString(), '|', false);
|
||||||
|
parts.erase(parts.begin());
|
||||||
|
|
||||||
|
if (api_path != utils::string::join(parts, '|')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return perform_action(
|
||||||
|
function_name,
|
||||||
|
[this, &iter](rocksdb::Transaction *txn) -> rocksdb::Status {
|
||||||
|
return txn->Delete(upload_family_, iter->key());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::remove_upload_active(const std::string &api_path)
|
||||||
|
-> bool {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
return perform_action(
|
||||||
|
function_name,
|
||||||
|
[this, &api_path](rocksdb::Transaction *txn) -> rocksdb::Status {
|
||||||
|
return txn->Delete(upload_active_family_, api_path);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::rename_resume(const std::string &from_api_path,
|
||||||
|
const std::string &to_api_path) -> bool {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
bool not_found{false};
|
||||||
|
std::string value;
|
||||||
|
auto res = perform_action(
|
||||||
|
function_name,
|
||||||
|
[this, &from_api_path, ¬_found, &value]() -> rocksdb::Status {
|
||||||
|
auto result = db_->Get(rocksdb::ReadOptions{}, from_api_path, &value);
|
||||||
|
not_found = result.IsNotFound();
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
if (not_found) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not res) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.empty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto data = json::parse(value);
|
||||||
|
resume_entry entry{
|
||||||
|
to_api_path,
|
||||||
|
data.at("chunk_size").get<std::uint64_t>(),
|
||||||
|
utils::string::to_dynamic_bitset(
|
||||||
|
data.at("read_state").get<std::string>()),
|
||||||
|
data.at("source_path").get<std::string>(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return perform_action(function_name,
|
||||||
|
[this, &entry, &from_api_path](
|
||||||
|
rocksdb::Transaction *txn) -> rocksdb::Status {
|
||||||
|
auto txn_res = remove_resume(from_api_path, txn);
|
||||||
|
if (not txn_res.ok()) {
|
||||||
|
return txn_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return add_resume(entry, txn);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} // namespace repertory
|
511
repertory/librepertory/src/db/impl/rdb_meta_db.cpp
Normal file
511
repertory/librepertory/src/db/impl/rdb_meta_db.cpp
Normal file
@ -0,0 +1,511 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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 "db/impl/rdb_meta_db.hpp"
|
||||||
|
|
||||||
|
#include "app_config.hpp"
|
||||||
|
#include "types/startup_exception.hpp"
|
||||||
|
#include "utils/error_utils.hpp"
|
||||||
|
#include "utils/file.hpp"
|
||||||
|
#include "utils/path.hpp"
|
||||||
|
#include "utils/string.hpp"
|
||||||
|
#include "utils/utils.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
rdb_meta_db::rdb_meta_db(const app_config &cfg) : cfg_(cfg) {
|
||||||
|
create_or_open(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
rdb_meta_db::~rdb_meta_db() { db_.reset(); }
|
||||||
|
|
||||||
|
void rdb_meta_db::create_or_open(bool clear) {
|
||||||
|
db_.reset();
|
||||||
|
|
||||||
|
auto families = std::vector<rocksdb::ColumnFamilyDescriptor>();
|
||||||
|
families.emplace_back(rocksdb::kDefaultColumnFamilyName,
|
||||||
|
rocksdb::ColumnFamilyOptions());
|
||||||
|
families.emplace_back("pinned", rocksdb::ColumnFamilyOptions());
|
||||||
|
families.emplace_back("size", rocksdb::ColumnFamilyOptions());
|
||||||
|
families.emplace_back("source", rocksdb::ColumnFamilyOptions());
|
||||||
|
|
||||||
|
auto handles = std::vector<rocksdb::ColumnFamilyHandle *>();
|
||||||
|
db_ = utils::create_rocksdb(cfg_, "provider_meta", families, handles, clear);
|
||||||
|
|
||||||
|
std::size_t idx{};
|
||||||
|
meta_family_ = handles.at(idx++);
|
||||||
|
pinned_family_ = handles.at(idx++);
|
||||||
|
size_family_ = handles.at(idx++);
|
||||||
|
source_family_ = handles.at(idx++);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rdb_meta_db::clear() { create_or_open(true); }
|
||||||
|
|
||||||
|
auto rdb_meta_db::create_iterator(rocksdb::ColumnFamilyHandle *family) const
|
||||||
|
-> std::shared_ptr<rocksdb::Iterator> {
|
||||||
|
return std::shared_ptr<rocksdb::Iterator>(
|
||||||
|
db_->NewIterator(rocksdb::ReadOptions{}, family));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_meta_db::get_api_path(const std::string &source_path,
|
||||||
|
std::string &api_path) const -> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
if (source_path.empty()) {
|
||||||
|
return api_error::item_not_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
return perform_action(function_name, [&]() -> rocksdb::Status {
|
||||||
|
return db_->Get(rocksdb::ReadOptions{}, source_family_, source_path,
|
||||||
|
&api_path);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_meta_db::get_api_path_list() const -> std::vector<std::string> {
|
||||||
|
std::vector<std::string> ret;
|
||||||
|
auto iter = create_iterator(meta_family_);
|
||||||
|
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
||||||
|
ret.push_back(iter->key().ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_meta_db::get_item_meta_json(const std::string &api_path,
|
||||||
|
json &json_data) const -> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
try {
|
||||||
|
json_data.clear();
|
||||||
|
|
||||||
|
{
|
||||||
|
std::string value;
|
||||||
|
auto res = perform_action(function_name, [&]() -> rocksdb::Status {
|
||||||
|
return db_->Get(rocksdb::ReadOptions{}, meta_family_, api_path, &value);
|
||||||
|
});
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not value.empty()) {
|
||||||
|
json_data = json::parse(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::string value;
|
||||||
|
auto res = perform_action(function_name, [&]() -> rocksdb::Status {
|
||||||
|
return db_->Get(rocksdb::ReadOptions{}, pinned_family_, api_path,
|
||||||
|
&value);
|
||||||
|
});
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (not value.empty()) {
|
||||||
|
json_data[META_PINNED] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::string value;
|
||||||
|
auto res = perform_action(function_name, [&]() -> rocksdb::Status {
|
||||||
|
return db_->Get(rocksdb::ReadOptions{}, size_family_, api_path, &value);
|
||||||
|
});
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (not value.empty()) {
|
||||||
|
json_data[META_SIZE] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return json_data.empty() ? api_error::item_not_found : api_error::success;
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
utils::error::raise_api_path_error(function_name, api_path, e,
|
||||||
|
"failed to get item meta");
|
||||||
|
}
|
||||||
|
|
||||||
|
return api_error::error;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_meta_db::get_item_meta(const std::string &api_path,
|
||||||
|
api_meta_map &meta) const -> api_error {
|
||||||
|
json json_data;
|
||||||
|
auto ret = get_item_meta_json(api_path, json_data);
|
||||||
|
if (ret != api_error::success) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto it = json_data.begin(); it != json_data.end(); ++it) {
|
||||||
|
meta[it.key()] = it.value().get<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_meta_db::get_item_meta(const std::string &api_path,
|
||||||
|
const std::string &key,
|
||||||
|
std::string &value) const -> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
if (key == META_PINNED) {
|
||||||
|
return perform_action(function_name, [&]() -> rocksdb::Status {
|
||||||
|
return db_->Get(rocksdb::ReadOptions{}, pinned_family_, api_path, &value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == META_SIZE) {
|
||||||
|
return perform_action(function_name, [&]() -> rocksdb::Status {
|
||||||
|
return db_->Get(rocksdb::ReadOptions{}, size_family_, api_path, &value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
json json_data;
|
||||||
|
auto ret = get_item_meta_json(api_path, json_data);
|
||||||
|
if (ret != api_error::success) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json_data.find(key) != json_data.end()) {
|
||||||
|
value = json_data[key].get<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_meta_db::get_pinned_files() const -> std::vector<std::string> {
|
||||||
|
std::vector<std::string> ret;
|
||||||
|
auto iter = create_iterator(pinned_family_);
|
||||||
|
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
||||||
|
if (not utils::string::to_bool(iter->value().ToString())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.push_back(iter->key().ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_meta_db::get_total_item_count() const -> std::uint64_t {
|
||||||
|
std::uint64_t ret{};
|
||||||
|
auto iter = create_iterator(meta_family_);
|
||||||
|
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
||||||
|
++ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_meta_db::get_total_size() const -> std::uint64_t {
|
||||||
|
std::uint64_t ret{};
|
||||||
|
auto iter = create_iterator(size_family_);
|
||||||
|
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
|
||||||
|
ret += utils::string::to_uint64(iter->value().ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_meta_db::perform_action(std::string_view function_name,
|
||||||
|
std::function<rocksdb::Status()> action)
|
||||||
|
-> api_error {
|
||||||
|
auto res = action();
|
||||||
|
if (res.ok()) {
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not res.IsNotFound()) {
|
||||||
|
utils::error::raise_error(function_name, res.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.IsNotFound() ? api_error::item_not_found : api_error::error;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_meta_db::perform_action(
|
||||||
|
std::string_view function_name,
|
||||||
|
std::function<rocksdb::Status(rocksdb::Transaction *txn)> action)
|
||||||
|
-> api_error {
|
||||||
|
std::unique_ptr<rocksdb::Transaction> txn{
|
||||||
|
db_->BeginTransaction(rocksdb::WriteOptions{},
|
||||||
|
rocksdb::TransactionOptions{}),
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto res = action(txn.get());
|
||||||
|
if (res.ok()) {
|
||||||
|
auto commit_res = txn->Commit();
|
||||||
|
if (commit_res.ok()) {
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::error::raise_error(function_name,
|
||||||
|
"rocksdb commit failed|" + res.ToString());
|
||||||
|
return api_error::error;
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::error::raise_error(function_name,
|
||||||
|
"rocksdb action failed|" + res.ToString());
|
||||||
|
} catch (const std::exception &ex) {
|
||||||
|
utils::error::raise_error(function_name, ex,
|
||||||
|
"failed to handle rocksdb action");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rollback_res = txn->Rollback();
|
||||||
|
utils::error::raise_error(function_name, "rocksdb rollback failed|" +
|
||||||
|
rollback_res.ToString());
|
||||||
|
return api_error::error;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rdb_meta_db::remove_api_path(const std::string &api_path) {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
std::string source_path;
|
||||||
|
auto res = get_item_meta(api_path, META_SOURCE, source_path);
|
||||||
|
if (res != api_error::success) {
|
||||||
|
utils::error::raise_api_path_error(function_name, api_path, res,
|
||||||
|
"failed to get source path");
|
||||||
|
}
|
||||||
|
|
||||||
|
res = perform_action(function_name,
|
||||||
|
[this, &api_path, &source_path](
|
||||||
|
rocksdb::Transaction *txn) -> rocksdb::Status {
|
||||||
|
return remove_api_path(api_path, source_path, txn);
|
||||||
|
});
|
||||||
|
if (res != api_error::success) {
|
||||||
|
utils::error::raise_api_path_error(function_name, api_path, res,
|
||||||
|
"failed to remove 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 txn_res = txn->Delete(pinned_family_, api_path);
|
||||||
|
if (not txn_res.ok()) {
|
||||||
|
return txn_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
txn_res = txn->Delete(size_family_, api_path);
|
||||||
|
if (not txn_res.ok()) {
|
||||||
|
return txn_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not source_path.empty()) {
|
||||||
|
txn_res = txn->Delete(source_family_, source_path);
|
||||||
|
if (not txn_res.ok()) {
|
||||||
|
return txn_res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return txn->Delete(meta_family_, api_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_meta_db::remove_item_meta(const std::string &api_path,
|
||||||
|
const std::string &key) -> api_error {
|
||||||
|
if (key == META_DIRECTORY || key == META_PINNED || key == META_SIZE ||
|
||||||
|
key == META_SOURCE) {
|
||||||
|
// TODO log warning for unsupported attributes
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
json json_data;
|
||||||
|
auto res = get_item_meta_json(api_path, json_data);
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_data.erase(key);
|
||||||
|
return update_item_meta(api_path, json_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_meta_db::rename_item_meta(const std::string &from_api_path,
|
||||||
|
const std::string &to_api_path)
|
||||||
|
-> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
json json_data;
|
||||||
|
auto res = get_item_meta_json(from_api_path, json_data);
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return perform_action(
|
||||||
|
function_name, [&](rocksdb::Transaction *txn) -> rocksdb::Status {
|
||||||
|
auto txn_res = remove_api_path(
|
||||||
|
from_api_path, json_data[META_SOURCE].get<std::string>(), txn);
|
||||||
|
if (not txn_res.ok()) {
|
||||||
|
return txn_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
rocksdb::Status status;
|
||||||
|
[[maybe_unused]] auto api_res =
|
||||||
|
update_item_meta(to_api_path, json_data, txn, &status);
|
||||||
|
return status;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_meta_db::set_item_meta(const std::string &api_path,
|
||||||
|
const std::string &key,
|
||||||
|
const std::string &value) -> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
if (key == META_PINNED) {
|
||||||
|
return perform_action(function_name,
|
||||||
|
[&](rocksdb::Transaction *txn) -> rocksdb::Status {
|
||||||
|
return txn->Put(pinned_family_, api_path, value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == META_SIZE) {
|
||||||
|
return perform_action(function_name,
|
||||||
|
[&](rocksdb::Transaction *txn) -> rocksdb::Status {
|
||||||
|
return txn->Put(size_family_, api_path, value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
json json_data;
|
||||||
|
auto res = get_item_meta_json(api_path, json_data);
|
||||||
|
if (res != api_error::success && res != api_error::item_not_found) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_data[key] = value;
|
||||||
|
|
||||||
|
return update_item_meta(api_path, json_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_meta_db::set_item_meta(const std::string &api_path,
|
||||||
|
const api_meta_map &meta) -> api_error {
|
||||||
|
json json_data;
|
||||||
|
auto res = get_item_meta_json(api_path, json_data);
|
||||||
|
if (res != api_error::success && res != api_error::item_not_found) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &data : meta) {
|
||||||
|
json_data[data.first] = data.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return update_item_meta(api_path, json_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_meta_db::update_item_meta(const std::string &api_path, json json_data,
|
||||||
|
rocksdb::Transaction *base_txn,
|
||||||
|
rocksdb::Status *status) -> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (not json_data.contains(META_PINNED)) {
|
||||||
|
json_data[META_PINNED] = utils::string::from_bool(false);
|
||||||
|
}
|
||||||
|
if (not json_data.contains(META_SIZE)) {
|
||||||
|
json_data[META_SIZE] = "0";
|
||||||
|
}
|
||||||
|
if (not json_data.contains(META_SOURCE)) {
|
||||||
|
json_data[META_SOURCE] = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto directory =
|
||||||
|
utils::string::to_bool(json_data.at(META_DIRECTORY).get<std::string>());
|
||||||
|
|
||||||
|
auto pinned = directory ? false
|
||||||
|
: utils::string::to_bool(
|
||||||
|
json_data.at(META_PINNED).get<std::string>());
|
||||||
|
auto size = directory ? std::uint64_t(0U)
|
||||||
|
: utils::string::to_uint64(
|
||||||
|
json_data.at(META_SIZE).get<std::string>());
|
||||||
|
auto source_path = directory ? std::string("")
|
||||||
|
: json_data.at(META_SOURCE).get<std::string>();
|
||||||
|
|
||||||
|
json_data[META_PINNED] = utils::string::from_bool(pinned);
|
||||||
|
json_data[META_SIZE] = std::to_string(size);
|
||||||
|
json_data[META_SOURCE] = source_path;
|
||||||
|
|
||||||
|
auto should_del_source{false};
|
||||||
|
std::string orig_source_path;
|
||||||
|
if (not directory) {
|
||||||
|
auto res = get_item_meta(api_path, META_SOURCE, orig_source_path);
|
||||||
|
if (res != api_error::success && res != api_error::item_not_found) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
should_del_source =
|
||||||
|
not orig_source_path.empty() && orig_source_path != source_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_data.erase(META_PINNED);
|
||||||
|
json_data.erase(META_SIZE);
|
||||||
|
|
||||||
|
const auto set_status = [&status](rocksdb::Status res) -> rocksdb::Status {
|
||||||
|
if (status != nullptr) {
|
||||||
|
*status = res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto do_transaction =
|
||||||
|
[&](rocksdb::Transaction *txn) -> rocksdb::Status {
|
||||||
|
if (should_del_source) {
|
||||||
|
auto res = set_status(txn->Delete(source_family_, orig_source_path));
|
||||||
|
if (not res.ok()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto res = set_status(
|
||||||
|
txn->Put(pinned_family_, api_path, utils::string::from_bool(pinned)));
|
||||||
|
if (not res.ok()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = set_status(txn->Put(size_family_, api_path, std::to_string(size)));
|
||||||
|
if (not res.ok()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not source_path.empty()) {
|
||||||
|
res = set_status(txn->Put(source_family_, source_path, api_path));
|
||||||
|
if (not res.ok()) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return set_status(txn->Put(meta_family_, api_path, json_data.dump()));
|
||||||
|
};
|
||||||
|
|
||||||
|
if (base_txn == nullptr) {
|
||||||
|
return perform_action(function_name, do_transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto res = set_status(do_transaction(base_txn));
|
||||||
|
if (res.ok()) {
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
utils::error::raise_api_path_error(function_name, api_path, e,
|
||||||
|
"failed to update item meta");
|
||||||
|
}
|
||||||
|
|
||||||
|
return api_error::error;
|
||||||
|
}
|
||||||
|
} // namespace repertory
|
334
repertory/librepertory/src/db/impl/sqlite_file_db.cpp
Normal file
334
repertory/librepertory/src/db/impl/sqlite_file_db.cpp
Normal file
@ -0,0 +1,334 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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 "db/impl/sqlite_file_db.hpp"
|
||||||
|
|
||||||
|
#include "app_config.hpp"
|
||||||
|
#include "types/startup_exception.hpp"
|
||||||
|
#include "utils/config.hpp"
|
||||||
|
#include "utils/db/sqlite/db_common.hpp"
|
||||||
|
#include "utils/db/sqlite/db_delete.hpp"
|
||||||
|
#include "utils/db/sqlite/db_insert.hpp"
|
||||||
|
#include "utils/db/sqlite/db_select.hpp"
|
||||||
|
#include "utils/db/sqlite/db_update.hpp"
|
||||||
|
#include "utils/error_utils.hpp"
|
||||||
|
#include "utils/file.hpp"
|
||||||
|
#include "utils/path.hpp"
|
||||||
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const std::string file_table = "file";
|
||||||
|
const std::map<std::string, std::string> sql_create_tables = {
|
||||||
|
{
|
||||||
|
{file_table},
|
||||||
|
{"CREATE TABLE IF NOT EXISTS " + file_table +
|
||||||
|
"("
|
||||||
|
"source_path TEXT PRIMARY KEY ASC, "
|
||||||
|
"api_path TEXT UNIQUE NOT NULL, "
|
||||||
|
"iv TEXT DEFAULT '' NOT NULL, "
|
||||||
|
"directory INTEGER NOT NULL, "
|
||||||
|
"size INTEGER DEFAULT 0 NOT NULL"
|
||||||
|
");"},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
sqlite_file_db::sqlite_file_db(const app_config &cfg) {
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
db_ = utils::db::sqlite::create_db(utils::path::combine(db_dir, {"file.db"}),
|
||||||
|
sql_create_tables);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
auto result = utils::db::sqlite::db_insert{*db_, file_table}
|
||||||
|
.column_value("api_path", api_path)
|
||||||
|
.column_value("directory", 1)
|
||||||
|
.column_value("source_path", source_path)
|
||||||
|
.go();
|
||||||
|
if (result.ok()) {
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::error::raise_api_path_error(
|
||||||
|
function_name, api_path, api_error::error,
|
||||||
|
fmt::format("failed to add directory|{}", result.get_error_str()));
|
||||||
|
return api_error::error;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_db::add_or_update_file(const i_file_db::file_data &data)
|
||||||
|
-> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
auto result =
|
||||||
|
utils::db::sqlite::db_insert{*db_, file_table}
|
||||||
|
.or_replace()
|
||||||
|
.column_value("api_path", data.api_path)
|
||||||
|
.column_value("directory", 0)
|
||||||
|
.column_value("iv", json(data.iv_list).dump())
|
||||||
|
.column_value("size", static_cast<std::int64_t>(data.file_size))
|
||||||
|
.column_value("source_path", data.source_path)
|
||||||
|
.go();
|
||||||
|
if (result.ok()) {
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::error::raise_api_path_error(
|
||||||
|
function_name, data.api_path, api_error::error,
|
||||||
|
fmt::format("failed to add file|{}", result.get_error_str()));
|
||||||
|
return api_error::error;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sqlite_file_db::clear() {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
auto result = utils::db::sqlite::db_delete{*db_, file_table}.go();
|
||||||
|
if (not result.ok()) {
|
||||||
|
utils::error::raise_error(function_name,
|
||||||
|
fmt::format("failed to clear file table|{}",
|
||||||
|
std::to_string(result.get_error())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_db::count() const -> std::uint64_t {
|
||||||
|
auto result = utils::db::sqlite::db_select{*db_, file_table}
|
||||||
|
.count("api_path", "count")
|
||||||
|
.go();
|
||||||
|
|
||||||
|
std::optional<utils::db::sqlite::db_result::row> row;
|
||||||
|
if (result.get_row(row) && row.has_value()) {
|
||||||
|
return static_cast<std::uint64_t>(
|
||||||
|
row->get_column("count").get_value<std::int64_t>());
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
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}
|
||||||
|
.column("api_path")
|
||||||
|
.where("source_path")
|
||||||
|
.equals(source_path)
|
||||||
|
.op()
|
||||||
|
.limit(1)
|
||||||
|
.go();
|
||||||
|
|
||||||
|
std::optional<utils::db::sqlite::db_result::row> row;
|
||||||
|
if (result.get_row(row) && row.has_value()) {
|
||||||
|
api_path = row->get_column("api_path").get_value<std::string>();
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 result = utils::db::sqlite::db_select{*db_, file_table}
|
||||||
|
.column("api_path")
|
||||||
|
.where("source_path")
|
||||||
|
.equals(source_path)
|
||||||
|
.and_()
|
||||||
|
.where("directory")
|
||||||
|
.equals(1)
|
||||||
|
.op()
|
||||||
|
.limit(1)
|
||||||
|
.go();
|
||||||
|
|
||||||
|
std::optional<utils::db::sqlite::db_result::row> row;
|
||||||
|
if (result.get_row(row) && row.has_value()) {
|
||||||
|
api_path = row->get_column("api_path").get_value<std::string>();
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 result = utils::db::sqlite::db_select{*db_, file_table}
|
||||||
|
.column("source_path")
|
||||||
|
.where("api_path")
|
||||||
|
.equals(api_path)
|
||||||
|
.and_()
|
||||||
|
.where("directory")
|
||||||
|
.equals(1)
|
||||||
|
.op()
|
||||||
|
.limit(1)
|
||||||
|
.go();
|
||||||
|
|
||||||
|
std::optional<utils::db::sqlite::db_result::row> row;
|
||||||
|
if (result.get_row(row) && row.has_value()) {
|
||||||
|
source_path = row->get_column("source_path").get_value<std::string>();
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 result = utils::db::sqlite::db_select{*db_, file_table}
|
||||||
|
.column("api_path")
|
||||||
|
.where("source_path")
|
||||||
|
.equals(source_path)
|
||||||
|
.and_()
|
||||||
|
.where("directory")
|
||||||
|
.equals(0)
|
||||||
|
.op()
|
||||||
|
.limit(1)
|
||||||
|
.go();
|
||||||
|
|
||||||
|
std::optional<utils::db::sqlite::db_result::row> row;
|
||||||
|
if (result.get_row(row) && row.has_value()) {
|
||||||
|
api_path = row->get_column("api_path").get_value<std::string>();
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
return api_error::item_not_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_db::get_file_data(const std::string &api_path,
|
||||||
|
i_file_db::file_data &data) const
|
||||||
|
-> api_error {
|
||||||
|
auto result = utils::db::sqlite::db_select{*db_, file_table}
|
||||||
|
.column("iv")
|
||||||
|
.column("size")
|
||||||
|
.column("source_path")
|
||||||
|
.where("api_path")
|
||||||
|
.equals(api_path)
|
||||||
|
.and_()
|
||||||
|
.where("directory")
|
||||||
|
.equals(0)
|
||||||
|
.op()
|
||||||
|
.limit(1)
|
||||||
|
.go();
|
||||||
|
|
||||||
|
std::optional<utils::db::sqlite::db_result::row> row;
|
||||||
|
if (result.get_row(row) && row.has_value()) {
|
||||||
|
data.api_path = api_path;
|
||||||
|
data.file_size = static_cast<std::uint64_t>(
|
||||||
|
row->get_column("size").get_value<std::int64_t>());
|
||||||
|
data.source_path = row->get_column("source_path").get_value<std::string>();
|
||||||
|
|
||||||
|
auto str_data = row->get_column("iv").get_value<std::string>();
|
||||||
|
if (not str_data.empty()) {
|
||||||
|
data.iv_list =
|
||||||
|
json::parse(str_data)
|
||||||
|
.get<std::vector<
|
||||||
|
std::array<unsigned char,
|
||||||
|
crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 result = utils::db::sqlite::db_select{*db_, file_table}
|
||||||
|
.column("source_path")
|
||||||
|
.where("api_path")
|
||||||
|
.equals(api_path)
|
||||||
|
.and_()
|
||||||
|
.where("directory")
|
||||||
|
.equals(0)
|
||||||
|
.op()
|
||||||
|
.limit(1)
|
||||||
|
.go();
|
||||||
|
|
||||||
|
std::optional<utils::db::sqlite::db_result::row> row;
|
||||||
|
if (result.get_row(row) && row.has_value()) {
|
||||||
|
source_path = row->get_column("source_path").get_value<std::string>();
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
return api_error::item_not_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_db::get_item_list() const
|
||||||
|
-> std::vector<i_file_db::file_info> {
|
||||||
|
std::vector<i_file_db::file_info> ret;
|
||||||
|
|
||||||
|
auto result = utils::db::sqlite::db_select{*db_, file_table}.go();
|
||||||
|
while (result.has_row()) {
|
||||||
|
std::optional<utils::db::sqlite::db_result::row> row;
|
||||||
|
if (result.get_row(row) && row.has_value()) {
|
||||||
|
ret.emplace_back(i_file_db::file_info{
|
||||||
|
row->get_column("api_path").get_value<std::string>(),
|
||||||
|
row->get_column("directory").get_value<std::int64_t>() == 1,
|
||||||
|
row->get_column("source_path").get_value<std::string>(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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 result = utils::db::sqlite::db_select{*db_, file_table}
|
||||||
|
.column("source_path")
|
||||||
|
.where("api_path")
|
||||||
|
.equals(api_path)
|
||||||
|
.op()
|
||||||
|
.limit(1)
|
||||||
|
.go();
|
||||||
|
|
||||||
|
std::optional<utils::db::sqlite::db_result::row> row;
|
||||||
|
if (result.get_row(row) && row.has_value()) {
|
||||||
|
source_path = row->get_column("source_path").get_value<std::string>();
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
return api_error::item_not_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_db::remove_item(const std::string &api_path) -> api_error {
|
||||||
|
auto result = utils::db::sqlite::db_delete{*db_, file_table}
|
||||||
|
.where("api_path")
|
||||||
|
.equals(api_path)
|
||||||
|
.go();
|
||||||
|
|
||||||
|
return result.ok() ? api_error::success : api_error::error;
|
||||||
|
}
|
||||||
|
} // namespace repertory
|
275
repertory/librepertory/src/db/impl/sqlite_file_mgr_db.cpp
Normal file
275
repertory/librepertory/src/db/impl/sqlite_file_mgr_db.cpp
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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 "db/impl/sqlite_file_mgr_db.hpp"
|
||||||
|
|
||||||
|
#include "app_config.hpp"
|
||||||
|
#include "types/startup_exception.hpp"
|
||||||
|
#include "utils/config.hpp"
|
||||||
|
#include "utils/db/sqlite/db_common.hpp"
|
||||||
|
#include "utils/db/sqlite/db_delete.hpp"
|
||||||
|
#include "utils/db/sqlite/db_insert.hpp"
|
||||||
|
#include "utils/db/sqlite/db_select.hpp"
|
||||||
|
#include "utils/db/sqlite/db_update.hpp"
|
||||||
|
#include "utils/error_utils.hpp"
|
||||||
|
#include "utils/file.hpp"
|
||||||
|
#include "utils/path.hpp"
|
||||||
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const std::string resume_table = "resume";
|
||||||
|
const std::string upload_table = "upload";
|
||||||
|
const std::string upload_active_table = "upload_active";
|
||||||
|
const std::map<std::string, std::string> sql_create_tables{
|
||||||
|
{
|
||||||
|
{resume_table},
|
||||||
|
{
|
||||||
|
"CREATE TABLE IF NOT EXISTS " + resume_table +
|
||||||
|
"("
|
||||||
|
"api_path TEXT PRIMARY KEY ASC, "
|
||||||
|
"chunk_size INTEGER, "
|
||||||
|
"read_state TEXT, "
|
||||||
|
"source_path TEXT"
|
||||||
|
");",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{upload_table},
|
||||||
|
{
|
||||||
|
"CREATE TABLE IF NOT EXISTS " + upload_table +
|
||||||
|
"("
|
||||||
|
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||||
|
"api_path TEXT UNIQUE, "
|
||||||
|
"source_path TEXT"
|
||||||
|
");",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{upload_active_table},
|
||||||
|
{
|
||||||
|
"CREATE TABLE IF NOT EXISTS " + upload_active_table +
|
||||||
|
"("
|
||||||
|
"api_path TEXT PRIMARY KEY ASC, "
|
||||||
|
"source_path TEXT"
|
||||||
|
");",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
sqlite_file_mgr_db::sqlite_file_mgr_db(const app_config &cfg) {
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
db_ = utils::db::sqlite::create_db(
|
||||||
|
utils::path::combine(db_dir, {"file_mgr.db"}), sql_create_tables);
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite_file_mgr_db::~sqlite_file_mgr_db() { db_.reset(); }
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::add_resume(const resume_entry &entry) -> bool {
|
||||||
|
return utils::db::sqlite::db_insert{*db_, resume_table}
|
||||||
|
.or_replace()
|
||||||
|
.column_value("api_path", entry.api_path)
|
||||||
|
.column_value("chunk_size", static_cast<std::int64_t>(entry.chunk_size))
|
||||||
|
.column_value("read_state",
|
||||||
|
utils::string::from_dynamic_bitset(entry.read_state))
|
||||||
|
.column_value("source_path", entry.source_path)
|
||||||
|
.go()
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::add_upload(const upload_entry &entry) -> bool {
|
||||||
|
return utils::db::sqlite::db_insert{*db_, upload_table}
|
||||||
|
.or_replace()
|
||||||
|
.column_value("api_path", entry.api_path)
|
||||||
|
.column_value("source_path", entry.source_path)
|
||||||
|
.go()
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::add_upload_active(const upload_active_entry &entry)
|
||||||
|
-> bool {
|
||||||
|
return utils::db::sqlite::db_insert{*db_, upload_active_table}
|
||||||
|
.or_replace()
|
||||||
|
.column_value("api_path", entry.api_path)
|
||||||
|
.column_value("source_path", entry.source_path)
|
||||||
|
.go()
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sqlite_file_mgr_db::clear() {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
auto result = utils::db::sqlite::db_delete{*db_, resume_table}.go();
|
||||||
|
if (not result.ok()) {
|
||||||
|
utils::error::raise_error(function_name,
|
||||||
|
"failed to clear resume table|" +
|
||||||
|
std::to_string(result.get_error()));
|
||||||
|
}
|
||||||
|
|
||||||
|
result = utils::db::sqlite::db_delete{*db_, upload_active_table}.go();
|
||||||
|
if (not result.ok()) {
|
||||||
|
utils::error::raise_error(function_name,
|
||||||
|
"failed to clear upload active table|" +
|
||||||
|
std::to_string(result.get_error()));
|
||||||
|
}
|
||||||
|
|
||||||
|
result = utils::db::sqlite::db_delete{*db_, upload_table}.go();
|
||||||
|
if (not result.ok()) {
|
||||||
|
utils::error::raise_error(function_name,
|
||||||
|
"failed to clear upload table|" +
|
||||||
|
std::to_string(result.get_error()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::get_next_upload() const
|
||||||
|
-> std::optional<upload_entry> {
|
||||||
|
auto result = utils::db::sqlite::db_select{*db_, upload_table}
|
||||||
|
.order_by("id", true)
|
||||||
|
.limit(1)
|
||||||
|
.go();
|
||||||
|
std::optional<utils::db::sqlite::db_result::row> row;
|
||||||
|
if (not result.get_row(row) || not row.has_value()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return upload_entry{
|
||||||
|
row->get_column("api_path").get_value<std::string>(),
|
||||||
|
row->get_column("source_path").get_value<std::string>(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::get_resume_list() const -> std::vector<resume_entry> {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
std::vector<resume_entry> ret;
|
||||||
|
auto result = utils::db::sqlite::db_select{*db_, resume_table}.go();
|
||||||
|
while (result.has_row()) {
|
||||||
|
try {
|
||||||
|
std::optional<utils::db::sqlite::db_result::row> row;
|
||||||
|
if (not result.get_row(row)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (not row.has_value()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.push_back(resume_entry{
|
||||||
|
row->get_column("api_path").get_value<std::string>(),
|
||||||
|
static_cast<std::uint64_t>(
|
||||||
|
row->get_column("chunk_size").get_value<std::int64_t>()),
|
||||||
|
utils::string::to_dynamic_bitset(
|
||||||
|
row->get_column("read_state").get_value<std::string>()),
|
||||||
|
row->get_column("source_path").get_value<std::string>(),
|
||||||
|
});
|
||||||
|
} catch (const std::exception &ex) {
|
||||||
|
utils::error::raise_error(function_name, ex, "query error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::get_upload(const std::string &api_path) const
|
||||||
|
-> std::optional<upload_entry> {
|
||||||
|
auto result = utils::db::sqlite::db_select{*db_, upload_table}
|
||||||
|
.where("api_path")
|
||||||
|
.equals(api_path)
|
||||||
|
.go();
|
||||||
|
std::optional<utils::db::sqlite::db_result::row> row;
|
||||||
|
if (not result.get_row(row) || not row.has_value()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return upload_entry{
|
||||||
|
row->get_column("api_path").get_value<std::string>(),
|
||||||
|
row->get_column("source_path").get_value<std::string>(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::get_upload_active_list() const
|
||||||
|
-> std::vector<upload_active_entry> {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
std::vector<upload_active_entry> ret;
|
||||||
|
auto result = utils::db::sqlite::db_select{*db_, upload_active_table}.go();
|
||||||
|
while (result.has_row()) {
|
||||||
|
try {
|
||||||
|
std::optional<utils::db::sqlite::db_result::row> row;
|
||||||
|
if (not result.get_row(row)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (not row.has_value()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.push_back(upload_active_entry{
|
||||||
|
row->get_column("api_path").get_value<std::string>(),
|
||||||
|
row->get_column("source_path").get_value<std::string>(),
|
||||||
|
});
|
||||||
|
} catch (const std::exception &ex) {
|
||||||
|
utils::error::raise_error(function_name, ex, "query error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::remove_resume(const std::string &api_path) -> bool {
|
||||||
|
return utils::db::sqlite::db_delete{*db_, resume_table}
|
||||||
|
.where("api_path")
|
||||||
|
.equals(api_path)
|
||||||
|
.go()
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::remove_upload(const std::string &api_path) -> bool {
|
||||||
|
return utils::db::sqlite::db_delete{*db_, upload_table}
|
||||||
|
.where("api_path")
|
||||||
|
.equals(api_path)
|
||||||
|
.go()
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::remove_upload_active(const std::string &api_path)
|
||||||
|
-> bool {
|
||||||
|
return utils::db::sqlite::db_delete{*db_, upload_active_table}
|
||||||
|
.where("api_path")
|
||||||
|
.equals(api_path)
|
||||||
|
.go()
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::rename_resume(const std::string &from_api_path,
|
||||||
|
const std::string &to_api_path) -> bool {
|
||||||
|
return utils::db::sqlite::db_update{*db_, resume_table}
|
||||||
|
.column_value("api_path", to_api_path)
|
||||||
|
.where("api_path")
|
||||||
|
.equals(from_api_path)
|
||||||
|
.go()
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
} // namespace repertory
|
@ -19,21 +19,21 @@
|
|||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#include "providers/meta_db.hpp"
|
#include "db/impl/sqlite_meta_db.hpp"
|
||||||
|
|
||||||
#include "app_config.hpp"
|
#include "app_config.hpp"
|
||||||
|
#include "types/startup_exception.hpp"
|
||||||
#include "utils/db/sqlite/db_common.hpp"
|
#include "utils/db/sqlite/db_common.hpp"
|
||||||
#include "utils/db/sqlite/db_delete.hpp"
|
#include "utils/db/sqlite/db_delete.hpp"
|
||||||
#include "utils/db/sqlite/db_insert.hpp"
|
#include "utils/db/sqlite/db_insert.hpp"
|
||||||
#include "utils/db/sqlite/db_select.hpp"
|
#include "utils/db/sqlite/db_select.hpp"
|
||||||
#include "utils/error_utils.hpp"
|
#include "utils/error_utils.hpp"
|
||||||
|
#include "utils/file.hpp"
|
||||||
#include "utils/path.hpp"
|
#include "utils/path.hpp"
|
||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
meta_db::meta_db(const app_config &cfg) {
|
sqlite_meta_db::sqlite_meta_db(const app_config &cfg) {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
|
||||||
|
|
||||||
const std::map<std::string, std::string> sql_create_tables{
|
const std::map<std::string, std::string> sql_create_tables{
|
||||||
{
|
{
|
||||||
{"meta"},
|
{"meta"},
|
||||||
@ -44,20 +44,39 @@ meta_db::meta_db(const app_config &cfg) {
|
|||||||
"data TEXT, "
|
"data TEXT, "
|
||||||
"directory INTEGER, "
|
"directory INTEGER, "
|
||||||
"pinned INTEGER, "
|
"pinned INTEGER, "
|
||||||
|
"size INTEGER, "
|
||||||
"source_path TEXT"
|
"source_path TEXT"
|
||||||
");"},
|
");"},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
db_ = utils::db::sqlite::create_db(
|
auto db_dir = utils::path::combine(cfg.get_data_directory(), {"db"});
|
||||||
utils::path::combine(cfg.get_data_directory(), {"meta.db"}),
|
if (not utils::file::directory{db_dir}.create_directory()) {
|
||||||
|
throw startup_exception(
|
||||||
|
fmt::format("failed to create db directory|", db_dir));
|
||||||
|
}
|
||||||
|
|
||||||
|
db_ = utils::db::sqlite::create_db(utils::path::combine(db_dir, {"meta.db"}),
|
||||||
sql_create_tables);
|
sql_create_tables);
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_db::~meta_db() { db_.reset(); }
|
sqlite_meta_db::~sqlite_meta_db() { db_.reset(); }
|
||||||
|
|
||||||
auto meta_db::get_api_path(const std::string &source_path,
|
void sqlite_meta_db::clear() {
|
||||||
std::string &api_path) -> api_error {
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
auto result = utils::db::sqlite::db_delete{*db_, table_name}.go();
|
||||||
|
if (result.ok()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::error::raise_error(function_name,
|
||||||
|
"failed to clear meta db|" +
|
||||||
|
std::to_string(result.get_error()));
|
||||||
|
}
|
||||||
|
|
||||||
|
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}
|
auto result = utils::db::sqlite::db_select{*db_, table_name}
|
||||||
.column("api_path")
|
.column("api_path")
|
||||||
.where("source_path")
|
.where("source_path")
|
||||||
@ -75,7 +94,7 @@ auto meta_db::get_api_path(const std::string &source_path,
|
|||||||
return api_error::item_not_found;
|
return api_error::item_not_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto meta_db::get_api_path_list() -> std::vector<std::string> {
|
auto sqlite_meta_db::get_api_path_list() const -> std::vector<std::string> {
|
||||||
std::vector<std::string> ret{};
|
std::vector<std::string> ret{};
|
||||||
|
|
||||||
auto result =
|
auto result =
|
||||||
@ -90,8 +109,8 @@ auto meta_db::get_api_path_list() -> std::vector<std::string> {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto meta_db::get_item_meta(const std::string &api_path, api_meta_map &meta)
|
auto sqlite_meta_db::get_item_meta(const std::string &api_path,
|
||||||
-> api_error {
|
api_meta_map &meta) const -> api_error {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
auto result = utils::db::sqlite::db_select{*db_, table_name}
|
auto result = utils::db::sqlite::db_select{*db_, table_name}
|
||||||
@ -114,9 +133,10 @@ auto meta_db::get_item_meta(const std::string &api_path, api_meta_map &meta)
|
|||||||
row->get_column("directory").get_value<std::int64_t>() == 1);
|
row->get_column("directory").get_value<std::int64_t>() == 1);
|
||||||
meta[META_PINNED] = utils::string::from_bool(
|
meta[META_PINNED] = utils::string::from_bool(
|
||||||
row->get_column("pinned").get_value<std::int64_t>() == 1);
|
row->get_column("pinned").get_value<std::int64_t>() == 1);
|
||||||
|
meta[META_SIZE] = std::to_string(static_cast<std::uint64_t>(
|
||||||
|
row->get_column("size").get_value<std::int64_t>()));
|
||||||
meta[META_SOURCE] =
|
meta[META_SOURCE] =
|
||||||
row->get_column("source_path").get_value<std::string>();
|
row->get_column("source_path").get_value<std::string>();
|
||||||
|
|
||||||
return api_error::success;
|
return api_error::success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,7 +149,8 @@ auto meta_db::get_item_meta(const std::string &api_path, api_meta_map &meta)
|
|||||||
return api_error::error;
|
return api_error::error;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto meta_db::get_item_meta(const std::string &api_path, const std::string &key,
|
auto sqlite_meta_db::get_item_meta(const std::string &api_path,
|
||||||
|
const std::string &key,
|
||||||
std::string &value) const -> api_error {
|
std::string &value) const -> api_error {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
@ -156,6 +177,9 @@ auto meta_db::get_item_meta(const std::string &api_path, const std::string &key,
|
|||||||
: key == META_DIRECTORY
|
: key == META_DIRECTORY
|
||||||
? utils::string::from_bool(
|
? utils::string::from_bool(
|
||||||
row->get_column("directory").get_value<std::int64_t>() == 1)
|
row->get_column("directory").get_value<std::int64_t>() == 1)
|
||||||
|
: key == META_SIZE
|
||||||
|
? std::to_string(static_cast<std::uint64_t>(
|
||||||
|
row->get_column("size").get_value<std::int64_t>()))
|
||||||
: json::parse(
|
: json::parse(
|
||||||
row->get_column("data").get_value<std::string>())[key]
|
row->get_column("data").get_value<std::string>())[key]
|
||||||
.get<std::string>();
|
.get<std::string>();
|
||||||
@ -171,7 +195,7 @@ auto meta_db::get_item_meta(const std::string &api_path, const std::string &key,
|
|||||||
return api_error::error;
|
return api_error::error;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto meta_db::get_pinned_files() const -> std::vector<std::string> {
|
auto sqlite_meta_db::get_pinned_files() const -> std::vector<std::string> {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
std::vector<std::string> ret{};
|
std::vector<std::string> ret{};
|
||||||
@ -195,7 +219,7 @@ auto meta_db::get_pinned_files() const -> std::vector<std::string> {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto meta_db::get_total_item_count() const -> std::uint64_t {
|
auto sqlite_meta_db::get_total_item_count() const -> std::uint64_t {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
std::uint64_t ret{};
|
std::uint64_t ret{};
|
||||||
@ -218,7 +242,29 @@ auto meta_db::get_total_item_count() const -> std::uint64_t {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void meta_db::remove_api_path(const std::string &api_path) {
|
auto sqlite_meta_db::get_total_size() const -> std::uint64_t {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto result = utils::db::sqlite::db_select{*db_, table_name}
|
||||||
|
.column("SUM(size) as total_size")
|
||||||
|
.where("directory")
|
||||||
|
.equals(0)
|
||||||
|
.go();
|
||||||
|
|
||||||
|
std::optional<utils::db::sqlite::db_result::row> row;
|
||||||
|
if (result.get_row(row) && row.has_value()) {
|
||||||
|
return static_cast<std::uint64_t>(
|
||||||
|
row->get_column("total_size").get_value<std::int64_t>());
|
||||||
|
}
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
utils::error::raise_error(function_name, e, "failed to get total size");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sqlite_meta_db::remove_api_path(const std::string &api_path) {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
auto result = utils::db::sqlite::db_delete{*db_, table_name}
|
auto result = utils::db::sqlite::db_delete{*db_, table_name}
|
||||||
@ -231,8 +277,14 @@ void meta_db::remove_api_path(const std::string &api_path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto meta_db::remove_item_meta(const std::string &api_path,
|
auto sqlite_meta_db::remove_item_meta(const std::string &api_path,
|
||||||
const std::string &key) -> api_error {
|
const std::string &key) -> api_error {
|
||||||
|
if (key == META_DIRECTORY || key == META_PINNED || key == META_SIZE ||
|
||||||
|
key == META_SOURCE) {
|
||||||
|
// TODO log warning for unsupported attributes
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
api_meta_map meta{};
|
api_meta_map meta{};
|
||||||
auto res = get_item_meta(api_path, meta);
|
auto res = get_item_meta(api_path, meta);
|
||||||
if (res != api_error::success) {
|
if (res != api_error::success) {
|
||||||
@ -243,8 +295,9 @@ auto meta_db::remove_item_meta(const std::string &api_path,
|
|||||||
return update_item_meta(api_path, meta);
|
return update_item_meta(api_path, meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto meta_db::rename_item_meta(const std::string &from_api_path,
|
auto sqlite_meta_db::rename_item_meta(const std::string &from_api_path,
|
||||||
const std::string &to_api_path) -> api_error {
|
const std::string &to_api_path)
|
||||||
|
-> api_error {
|
||||||
api_meta_map meta{};
|
api_meta_map meta{};
|
||||||
auto res = get_item_meta(from_api_path, meta);
|
auto res = get_item_meta(from_api_path, meta);
|
||||||
if (res != api_error::success) {
|
if (res != api_error::success) {
|
||||||
@ -255,12 +308,13 @@ auto meta_db::rename_item_meta(const std::string &from_api_path,
|
|||||||
return update_item_meta(to_api_path, meta);
|
return update_item_meta(to_api_path, meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto meta_db::set_item_meta(const std::string &api_path, const std::string &key,
|
auto sqlite_meta_db::set_item_meta(const std::string &api_path,
|
||||||
|
const std::string &key,
|
||||||
const std::string &value) -> api_error {
|
const std::string &value) -> api_error {
|
||||||
return set_item_meta(api_path, {{key, value}});
|
return set_item_meta(api_path, {{key, value}});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto meta_db::set_item_meta(const std::string &api_path,
|
auto sqlite_meta_db::set_item_meta(const std::string &api_path,
|
||||||
const api_meta_map &meta) -> api_error {
|
const api_meta_map &meta) -> api_error {
|
||||||
api_meta_map existing_meta{};
|
api_meta_map existing_meta{};
|
||||||
if (get_item_meta(api_path, existing_meta) != api_error::success) {
|
if (get_item_meta(api_path, existing_meta) != api_error::success) {
|
||||||
@ -274,16 +328,31 @@ auto meta_db::set_item_meta(const std::string &api_path,
|
|||||||
return update_item_meta(api_path, existing_meta);
|
return update_item_meta(api_path, existing_meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto meta_db::update_item_meta(const std::string &api_path, api_meta_map meta)
|
auto sqlite_meta_db::update_item_meta(const std::string &api_path,
|
||||||
-> api_error {
|
api_meta_map meta) -> api_error {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
auto directory = utils::string::to_bool(meta[META_DIRECTORY]);
|
try {
|
||||||
auto pinned = utils::string::to_bool(meta[META_PINNED]);
|
if (meta[META_PINNED].empty()) {
|
||||||
auto source_path = meta[META_SOURCE];
|
meta[META_PINNED] = utils::string::from_bool(false);
|
||||||
|
}
|
||||||
|
if (meta[META_SIZE].empty()) {
|
||||||
|
meta[META_SIZE] = "0";
|
||||||
|
}
|
||||||
|
if (meta[META_SOURCE].empty()) {
|
||||||
|
meta[META_SOURCE] = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto directory = utils::string::to_bool(meta.at(META_DIRECTORY));
|
||||||
|
auto pinned =
|
||||||
|
directory ? false : utils::string::to_bool(meta.at(META_PINNED));
|
||||||
|
auto size = directory ? std::uint64_t(0U)
|
||||||
|
: utils::string::to_uint64(meta.at(META_SIZE));
|
||||||
|
auto source_path = directory ? std::string("") : meta.at(META_SOURCE);
|
||||||
|
|
||||||
meta.erase(META_DIRECTORY);
|
meta.erase(META_DIRECTORY);
|
||||||
meta.erase(META_PINNED);
|
meta.erase(META_PINNED);
|
||||||
|
meta.erase(META_SIZE);
|
||||||
meta.erase(META_SOURCE);
|
meta.erase(META_SOURCE);
|
||||||
|
|
||||||
auto result = utils::db::sqlite::db_insert{*db_, table_name}
|
auto result = utils::db::sqlite::db_insert{*db_, table_name}
|
||||||
@ -292,6 +361,7 @@ auto meta_db::update_item_meta(const std::string &api_path, api_meta_map meta)
|
|||||||
.column_value("data", nlohmann::json(meta).dump())
|
.column_value("data", nlohmann::json(meta).dump())
|
||||||
.column_value("directory", directory ? 1 : 0)
|
.column_value("directory", directory ? 1 : 0)
|
||||||
.column_value("pinned", pinned ? 1 : 0)
|
.column_value("pinned", pinned ? 1 : 0)
|
||||||
|
.column_value("size", static_cast<std::int64_t>(size))
|
||||||
.column_value("source_path", source_path)
|
.column_value("source_path", source_path)
|
||||||
.go();
|
.go();
|
||||||
if (not result.ok()) {
|
if (not result.ok()) {
|
||||||
@ -302,5 +372,11 @@ auto meta_db::update_item_meta(const std::string &api_path, api_meta_map meta)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return api_error::success;
|
return api_error::success;
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
utils::error::raise_api_path_error(function_name, api_path, e,
|
||||||
|
"failed to update item meta");
|
||||||
|
}
|
||||||
|
|
||||||
|
return api_error::error;
|
||||||
}
|
}
|
||||||
} // namespace repertory
|
} // namespace repertory
|
38
repertory/librepertory/src/db/meta_db.cpp
Normal file
38
repertory/librepertory/src/db/meta_db.cpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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 "db/meta_db.hpp"
|
||||||
|
|
||||||
|
#include "app_config.hpp"
|
||||||
|
#include "db/impl/rdb_meta_db.hpp"
|
||||||
|
#include "db/impl/sqlite_meta_db.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
auto create_meta_db(const app_config &cfg) -> std::unique_ptr<i_meta_db> {
|
||||||
|
switch (cfg.get_database_type()) {
|
||||||
|
case database_type::sqlite:
|
||||||
|
return std::make_unique<sqlite_meta_db>(cfg);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return std::make_unique<rdb_meta_db>(cfg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace repertory
|
@ -115,7 +115,7 @@ auto directory_iterator::get_directory_item(const std::string &api_path,
|
|||||||
|
|
||||||
auto directory_iterator::get_json(std::size_t offset, json &item) -> int {
|
auto directory_iterator::get_json(std::size_t offset, json &item) -> int {
|
||||||
if (offset < items_.size()) {
|
if (offset < items_.size()) {
|
||||||
item = items_[offset].to_json();
|
item = json(items_.at(offset));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,44 +30,35 @@
|
|||||||
#include "utils/file_utils.hpp"
|
#include "utils/file_utils.hpp"
|
||||||
#include "utils/time.hpp"
|
#include "utils/time.hpp"
|
||||||
#include "utils/utils.hpp"
|
#include "utils/utils.hpp"
|
||||||
|
#include <spdlog/fmt/bundled/base.h>
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
auto eviction::check_minimum_requirements(const std::string &file_path)
|
auto eviction::check_minimum_requirements(const std::string &file_path)
|
||||||
-> bool {
|
-> bool {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
auto opt_size = utils::file::file{file_path}.size();
|
auto file = utils::file::file{file_path};
|
||||||
if (not opt_size.has_value()) {
|
auto reference_time = file.get_time(config_.get_eviction_uses_accessed_time()
|
||||||
utils::error::raise_error(function_name, utils::get_last_error_code(),
|
|
||||||
file_path, "failed to get file size");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto file_size{opt_size.value()};
|
|
||||||
if (file_size == 0U) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto reference_time = utils::file::file{file_path}.get_time(
|
|
||||||
config_.get_eviction_uses_accessed_time()
|
|
||||||
? utils::file::time_type::accessed
|
? utils::file::time_type::accessed
|
||||||
: utils::file::time_type::modified);
|
: utils::file::time_type::modified);
|
||||||
|
|
||||||
if (not reference_time.has_value()) {
|
if (not reference_time.has_value()) {
|
||||||
|
utils::error::raise_error(function_name, utils::get_last_error_code(),
|
||||||
|
file_path, "failed to get file time");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto delay = (config_.get_eviction_delay_mins() * 60UL) *
|
auto delay =
|
||||||
|
static_cast<std::uint64_t>(config_.get_eviction_delay_mins() * 60U) *
|
||||||
utils::time::NANOS_PER_SECOND;
|
utils::time::NANOS_PER_SECOND;
|
||||||
return ((reference_time.value() + static_cast<std::uint64_t>(delay)) <=
|
return (reference_time.value() + delay) <= utils::time::get_time_now();
|
||||||
utils::time::get_time_now());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto eviction::get_filtered_cached_files() -> std::deque<std::string> {
|
auto eviction::get_filtered_cached_files() -> std::deque<std::string> {
|
||||||
auto list =
|
auto list =
|
||||||
utils::file::get_directory_files(config_.get_cache_directory(), true);
|
utils::file::get_directory_files(config_.get_cache_directory(), true);
|
||||||
list.erase(std::remove_if(list.begin(), list.end(),
|
list.erase(std::remove_if(list.begin(), list.end(),
|
||||||
[this](const std::string &path) -> bool {
|
[this](auto &&path) -> bool {
|
||||||
return not this->check_minimum_requirements(path);
|
return not this->check_minimum_requirements(path);
|
||||||
}),
|
}),
|
||||||
list.end());
|
list.end());
|
||||||
@ -77,65 +68,38 @@ auto eviction::get_filtered_cached_files() -> std::deque<std::string> {
|
|||||||
void eviction::service_function() {
|
void eviction::service_function() {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
auto should_evict = true;
|
|
||||||
|
|
||||||
// Handle maximum cache size eviction
|
|
||||||
auto used_bytes =
|
|
||||||
utils::file::directory{config_.get_cache_directory()}.size();
|
|
||||||
if (config_.get_enable_max_cache_size()) {
|
|
||||||
should_evict = (used_bytes > config_.get_max_cache_size_bytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (should_evict) {
|
|
||||||
// Remove cached source files that don't meet minimum requirements
|
|
||||||
auto cached_files_list = get_filtered_cached_files();
|
auto cached_files_list = get_filtered_cached_files();
|
||||||
while (not get_stop_requested() && should_evict &&
|
auto was_file_evicted{false};
|
||||||
not cached_files_list.empty()) {
|
while (not get_stop_requested() && not cached_files_list.empty()) {
|
||||||
|
auto file_path = cached_files_list.front();
|
||||||
|
cached_files_list.pop_front();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
std::string api_path;
|
std::string api_path;
|
||||||
if (provider_.get_api_path_from_source(
|
auto res = provider_.get_api_path_from_source(file_path, api_path);
|
||||||
cached_files_list.front(), api_path) == api_error::success) {
|
if (res != api_error::success) {
|
||||||
api_file file{};
|
continue;
|
||||||
filesystem_item fsi{};
|
|
||||||
if (provider_.get_filesystem_item_and_file(api_path, file, fsi) ==
|
|
||||||
api_error::success) {
|
|
||||||
// Only evict files that match expected size
|
|
||||||
auto opt_size = utils::file::file{cached_files_list.front()}.size();
|
|
||||||
if (opt_size.has_value()) {
|
|
||||||
auto file_size{opt_size.value()};
|
|
||||||
if (file_size == fsi.size) {
|
|
||||||
// Try to evict file
|
|
||||||
if (fm_.evict_file(fsi.api_path) &&
|
|
||||||
config_.get_enable_max_cache_size()) {
|
|
||||||
// Restrict number of items evicted if maximum cache size is
|
|
||||||
// enabled
|
|
||||||
used_bytes -= file_size;
|
|
||||||
should_evict =
|
|
||||||
(used_bytes > config_.get_max_cache_size_bytes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
utils::error::raise_api_path_error(
|
|
||||||
function_name, file.api_path, file.source_path,
|
|
||||||
utils::get_last_error_code(), "failed to get file size");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (file_mgr_.evict_file(api_path)) {
|
||||||
|
was_file_evicted = true;
|
||||||
}
|
}
|
||||||
} catch (const std::exception &ex) {
|
} catch (const std::exception &ex) {
|
||||||
utils::error::raise_error(function_name, ex,
|
utils::error::raise_error(
|
||||||
"failed to process cached file|sp|" +
|
function_name, ex,
|
||||||
cached_files_list.front());
|
fmt::format("failed to process cached file|sp|{}", file_path));
|
||||||
}
|
|
||||||
|
|
||||||
cached_files_list.pop_front();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not get_stop_requested()) {
|
if (get_stop_requested() || was_file_evicted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
unique_mutex_lock lock(get_mutex());
|
unique_mutex_lock lock(get_mutex());
|
||||||
if (not get_stop_requested()) {
|
if (get_stop_requested()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
get_notify().wait_for(lock, 30s);
|
get_notify().wait_for(lock, 30s);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "initialize.hpp"
|
#include "initialize.hpp"
|
||||||
#include "platform/platform.hpp"
|
#include "platform/platform.hpp"
|
||||||
#include "utils/collection.hpp"
|
#include "utils/collection.hpp"
|
||||||
|
#include "utils/error_utils.hpp"
|
||||||
#include "utils/file_utils.hpp"
|
#include "utils/file_utils.hpp"
|
||||||
#include "utils/path.hpp"
|
#include "utils/path.hpp"
|
||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
@ -40,47 +41,37 @@ auto fuse_base::instance() -> fuse_base & {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fuse_base::fuse_base(app_config &config) : config_(config) {
|
fuse_base::fuse_base(app_config &config) : config_(config) {
|
||||||
fuse_ops_.getattr = fuse_base::getattr_;
|
fuse_ops_.access = fuse_base::access_;
|
||||||
fuse_ops_.mkdir = fuse_base::mkdir_;
|
|
||||||
fuse_ops_.unlink = fuse_base::unlink_;
|
|
||||||
fuse_ops_.rmdir = fuse_base::rmdir_;
|
|
||||||
fuse_ops_.rename = fuse_base::rename_;
|
|
||||||
fuse_ops_.chmod = fuse_base::chmod_;
|
fuse_ops_.chmod = fuse_base::chmod_;
|
||||||
fuse_ops_.chown = fuse_base::chown_;
|
fuse_ops_.chown = fuse_base::chown_;
|
||||||
fuse_ops_.truncate = fuse_base::truncate_;
|
fuse_ops_.create = fuse_base::create_;
|
||||||
|
fuse_ops_.destroy = fuse_base::destroy_;
|
||||||
|
fuse_ops_.fallocate = fuse_base::fallocate_;
|
||||||
|
fuse_ops_.fsync = fuse_base::fsync_;
|
||||||
|
fuse_ops_.getattr = fuse_base::getattr_;
|
||||||
|
fuse_ops_.init = fuse_base::init_;
|
||||||
|
fuse_ops_.mkdir = fuse_base::mkdir_;
|
||||||
fuse_ops_.open = fuse_base::open_;
|
fuse_ops_.open = fuse_base::open_;
|
||||||
|
fuse_ops_.opendir = fuse_base::opendir_;
|
||||||
fuse_ops_.read = fuse_base::read_;
|
fuse_ops_.read = fuse_base::read_;
|
||||||
fuse_ops_.write = fuse_base::write_;
|
fuse_ops_.readdir = fuse_base::readdir_;
|
||||||
|
fuse_ops_.release = fuse_base::release_;
|
||||||
|
fuse_ops_.releasedir = fuse_base::releasedir_;
|
||||||
|
fuse_ops_.rename = fuse_base::rename_;
|
||||||
|
fuse_ops_.rmdir = fuse_base::rmdir_;
|
||||||
|
fuse_ops_.truncate = fuse_base::truncate_;
|
||||||
#if !defined(__APPLE__)
|
#if !defined(__APPLE__)
|
||||||
fuse_ops_.statfs = fuse_base::statfs_;
|
fuse_ops_.statfs = fuse_base::statfs_;
|
||||||
#endif // __APPLE__
|
#endif // __APPLE__
|
||||||
fuse_ops_.release = fuse_base::release_;
|
fuse_ops_.unlink = fuse_base::unlink_;
|
||||||
fuse_ops_.fsync = fuse_base::fsync_;
|
fuse_ops_.utimens = fuse_base::utimens_;
|
||||||
|
fuse_ops_.write = fuse_base::write_;
|
||||||
#if defined(HAS_SETXATTR)
|
#if defined(HAS_SETXATTR)
|
||||||
fuse_ops_.setxattr = fuse_base::setxattr_;
|
|
||||||
fuse_ops_.getxattr = fuse_base::getxattr_;
|
fuse_ops_.getxattr = fuse_base::getxattr_;
|
||||||
fuse_ops_.listxattr = fuse_base::listxattr_;
|
fuse_ops_.listxattr = fuse_base::listxattr_;
|
||||||
fuse_ops_.removexattr = fuse_base::removexattr_;
|
fuse_ops_.removexattr = fuse_base::removexattr_;
|
||||||
#endif // HAS_SETXATTR
|
fuse_ops_.setxattr = fuse_base::setxattr_;
|
||||||
fuse_ops_.opendir = fuse_base::opendir_;
|
#endif // defined(HAS_SETXATTR)
|
||||||
fuse_ops_.readdir = fuse_base::readdir_;
|
|
||||||
fuse_ops_.releasedir = fuse_base::releasedir_;
|
|
||||||
fuse_ops_.init = fuse_base::init_;
|
|
||||||
fuse_ops_.destroy = fuse_base::destroy_;
|
|
||||||
fuse_ops_.access = fuse_base::access_;
|
|
||||||
fuse_ops_.create = fuse_base::create_;
|
|
||||||
#if FUSE_USE_VERSION < 30
|
|
||||||
fuse_ops_.ftruncate = fuse_base::ftruncate_;
|
|
||||||
fuse_ops_.fgetattr = fuse_base::fgetattr_;
|
|
||||||
#endif
|
|
||||||
fuse_ops_.utimens = fuse_base::utimens_;
|
|
||||||
#if FUSE_USE_VERSION < 30
|
|
||||||
fuse_ops_.flag_nullpath_ok = 0;
|
|
||||||
fuse_ops_.flag_nopath = 0;
|
|
||||||
fuse_ops_.flag_utime_omit_ok = 1;
|
|
||||||
fuse_ops_.flag_reserved = 0;
|
|
||||||
#endif
|
|
||||||
fuse_ops_.fallocate = fuse_base::fallocate_;
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
fuse_ops_.chflags = fuse_base::chflags_;
|
fuse_ops_.chflags = fuse_base::chflags_;
|
||||||
fuse_ops_.fsetattr_x = fuse_base::fsetattr_x_;
|
fuse_ops_.fsetattr_x = fuse_base::fsetattr_x_;
|
||||||
@ -91,7 +82,13 @@ fuse_base::fuse_base(app_config &config) : config_(config) {
|
|||||||
fuse_ops_.setcrtime = fuse_base::setcrtime_;
|
fuse_ops_.setcrtime = fuse_base::setcrtime_;
|
||||||
fuse_ops_.setvolname = fuse_base::setvolname_;
|
fuse_ops_.setvolname = fuse_base::setvolname_;
|
||||||
fuse_ops_.statfs_x = fuse_base::statfs_x_;
|
fuse_ops_.statfs_x = fuse_base::statfs_x_;
|
||||||
#endif // __APPLE__
|
#endif // defined(__APPLE__)
|
||||||
|
#if FUSE_USE_VERSION < 30
|
||||||
|
fuse_ops_.flag_nullpath_ok = 0;
|
||||||
|
fuse_ops_.flag_nopath = 0;
|
||||||
|
fuse_ops_.flag_utime_omit_ok = 1;
|
||||||
|
fuse_ops_.flag_reserved = 0;
|
||||||
|
#endif // FUSE_USE_VERSION < 30
|
||||||
|
|
||||||
E_SUBSCRIBE_EXACT(unmount_requested, [this](const unmount_requested &) {
|
E_SUBSCRIBE_EXACT(unmount_requested, [this](const unmount_requested &) {
|
||||||
std::thread([this]() { this->shutdown(); }).detach();
|
std::thread([this]() { this->shutdown(); }).detach();
|
||||||
@ -121,8 +118,8 @@ auto fuse_base::chflags_(const char *path, uint32_t flags) -> int {
|
|||||||
#endif // __APPLE__
|
#endif // __APPLE__
|
||||||
|
|
||||||
#if FUSE_USE_VERSION >= 30
|
#if FUSE_USE_VERSION >= 30
|
||||||
auto fuse_base::chmod_(const char *path, mode_t mode, struct fuse_file_info *fi)
|
auto fuse_base::chmod_(const char *path, mode_t mode,
|
||||||
-> int {
|
struct fuse_file_info *fi) -> int {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
return instance().execute_callback(
|
return instance().execute_callback(
|
||||||
@ -189,7 +186,7 @@ void fuse_base::display_options(
|
|||||||
#if FUSE_USE_VERSION >= 30
|
#if FUSE_USE_VERSION >= 30
|
||||||
fuse_cmdline_help();
|
fuse_cmdline_help();
|
||||||
#else
|
#else
|
||||||
struct fuse_operations fuse_ops{};
|
struct fuse_operations fuse_ops {};
|
||||||
fuse_main(args.size(),
|
fuse_main(args.size(),
|
||||||
reinterpret_cast<char **>(const_cast<char **>(args.data())),
|
reinterpret_cast<char **>(const_cast<char **>(args.data())),
|
||||||
&fuse_ops, nullptr);
|
&fuse_ops, nullptr);
|
||||||
@ -199,7 +196,7 @@ void fuse_base::display_options(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void fuse_base::display_version_information(std::vector<const char *> args) {
|
void fuse_base::display_version_information(std::vector<const char *> args) {
|
||||||
struct fuse_operations fuse_ops{};
|
struct fuse_operations fuse_ops {};
|
||||||
fuse_main(static_cast<int>(args.size()),
|
fuse_main(static_cast<int>(args.size()),
|
||||||
reinterpret_cast<char **>(const_cast<char **>(args.data())),
|
reinterpret_cast<char **>(const_cast<char **>(args.data())),
|
||||||
&fuse_ops, nullptr);
|
&fuse_ops, nullptr);
|
||||||
@ -337,8 +334,8 @@ auto fuse_base::getxtimes_(const char *path, struct timespec *bkuptime,
|
|||||||
#endif // __APPLE__
|
#endif // __APPLE__
|
||||||
|
|
||||||
#if FUSE_USE_VERSION >= 30
|
#if FUSE_USE_VERSION >= 30
|
||||||
auto fuse_base::init_(struct fuse_conn_info *conn, struct fuse_config *cfg)
|
auto fuse_base::init_(struct fuse_conn_info *conn,
|
||||||
-> void * {
|
struct fuse_config *cfg) -> void * {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
return execute_void_pointer_callback(function_name, [&]() -> void * {
|
return execute_void_pointer_callback(function_name, [&]() -> void * {
|
||||||
@ -411,7 +408,7 @@ auto fuse_base::mount(std::vector<std::string> args) -> int {
|
|||||||
|
|
||||||
char *mount_location{nullptr};
|
char *mount_location{nullptr};
|
||||||
#if FUSE_USE_VERSION >= 30
|
#if FUSE_USE_VERSION >= 30
|
||||||
struct fuse_cmdline_opts opts{};
|
struct fuse_cmdline_opts opts {};
|
||||||
fuse_parse_cmdline(&fa, &opts);
|
fuse_parse_cmdline(&fa, &opts);
|
||||||
mount_location = opts.mountpoint;
|
mount_location = opts.mountpoint;
|
||||||
#else
|
#else
|
||||||
@ -480,8 +477,8 @@ auto fuse_base::read_(const char *path, char *buffer, size_t read_size,
|
|||||||
#if FUSE_USE_VERSION >= 30
|
#if FUSE_USE_VERSION >= 30
|
||||||
auto fuse_base::readdir_(const char *path, void *buf,
|
auto fuse_base::readdir_(const char *path, void *buf,
|
||||||
fuse_fill_dir_t fuse_fill_dir, off_t offset,
|
fuse_fill_dir_t fuse_fill_dir, off_t offset,
|
||||||
struct fuse_file_info *fi, fuse_readdir_flags flags)
|
struct fuse_file_info *fi,
|
||||||
-> int {
|
fuse_readdir_flags flags) -> int {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
return instance().execute_callback(
|
return instance().execute_callback(
|
||||||
@ -513,8 +510,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)
|
auto fuse_base::releasedir_(const char *path,
|
||||||
-> int {
|
struct fuse_file_info *fi) -> int {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
return instance().execute_callback(
|
return instance().execute_callback(
|
||||||
@ -524,8 +521,8 @@ auto fuse_base::releasedir_(const char *path, struct fuse_file_info *fi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if FUSE_USE_VERSION >= 30
|
#if FUSE_USE_VERSION >= 30
|
||||||
auto fuse_base::rename_(const char *from, const char *to, unsigned int flags)
|
auto fuse_base::rename_(const char *from, const char *to,
|
||||||
-> int {
|
unsigned int flags) -> int {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
return instance().execute_callback(
|
return instance().execute_callback(
|
||||||
@ -768,8 +765,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)
|
auto fuse_base::setbkuptime_(const char *path,
|
||||||
-> int {
|
const struct timespec *bkuptime) -> int {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
return instance().execute_callback(
|
return instance().execute_callback(
|
||||||
@ -778,8 +775,8 @@ auto fuse_base::setbkuptime_(const char *path, const struct timespec *bkuptime)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto fuse_base::setchgtime_(const char *path, const struct timespec *chgtime)
|
auto fuse_base::setchgtime_(const char *path,
|
||||||
-> int {
|
const struct timespec *chgtime) -> int {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
return instance().execute_callback(
|
return instance().execute_callback(
|
||||||
@ -788,8 +785,8 @@ auto fuse_base::setchgtime_(const char *path, const struct timespec *chgtime)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto fuse_base::setcrtime_(const char *path, const struct timespec *crtime)
|
auto fuse_base::setcrtime_(const char *path,
|
||||||
-> int {
|
const struct timespec *crtime) -> int {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
return instance().execute_callback(
|
return instance().execute_callback(
|
||||||
|
@ -88,7 +88,7 @@ auto fuse_drive::chown_impl(std::string api_path, uid_t uid,
|
|||||||
api_path, X_OK, [&](api_meta_map &meta) -> api_error {
|
api_path, X_OK, [&](api_meta_map &meta) -> api_error {
|
||||||
meta.clear();
|
meta.clear();
|
||||||
if (uid != static_cast<uid_t>(-1)) {
|
if (uid != static_cast<uid_t>(-1)) {
|
||||||
if (get_effective_uid() != 0) {
|
if (get_effective_uid() != 0 && get_effective_uid() != uid) {
|
||||||
return api_error::permission_denied;
|
return api_error::permission_denied;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,21 +116,16 @@ auto fuse_drive::create_impl(std::string api_path, mode_t mode,
|
|||||||
struct fuse_file_info *file_info) -> api_error {
|
struct fuse_file_info *file_info) -> api_error {
|
||||||
file_info->fh = 0U;
|
file_info->fh = 0U;
|
||||||
|
|
||||||
const auto is_directory_op =
|
auto is_append_op = ((file_info->flags & O_APPEND) == O_APPEND);
|
||||||
((file_info->flags & O_DIRECTORY) == O_DIRECTORY);
|
auto is_create_op = ((file_info->flags & O_CREAT) == O_CREAT);
|
||||||
const auto is_create_op = ((file_info->flags & O_CREAT) == O_CREAT);
|
auto is_directory_op = ((file_info->flags & O_DIRECTORY) == O_DIRECTORY);
|
||||||
const auto is_truncate_op = (((file_info->flags & O_TRUNC) != 0) &&
|
auto is_exclusive = ((file_info->flags & O_EXCL) == O_EXCL);
|
||||||
(((file_info->flags & O_WRONLY) != 0) ||
|
auto is_read_write_op = ((file_info->flags & O_RDWR) == O_RDWR);
|
||||||
((file_info->flags & O_RDWR) != 0)));
|
auto is_truncate_op = ((file_info->flags & O_TRUNC) == O_TRUNC);
|
||||||
|
auto is_write_only_op = ((file_info->flags & O_WRONLY) == O_WRONLY);
|
||||||
|
|
||||||
if (((file_info->flags & O_WRONLY) != 0) ||
|
if (is_create_op && is_append_op && is_truncate_op) {
|
||||||
((file_info->flags & O_RDWR) != 0)) {
|
return api_error::invalid_operation;
|
||||||
const auto res = provider_.is_file_writeable(api_path)
|
|
||||||
? api_error::success
|
|
||||||
: api_error::permission_denied;
|
|
||||||
if (res != api_error::success) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto res = check_parent_access(api_path, X_OK);
|
auto res = check_parent_access(api_path, X_OK);
|
||||||
@ -139,37 +134,65 @@ auto fuse_drive::create_impl(std::string api_path, mode_t mode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_create_op) {
|
if (is_create_op) {
|
||||||
if ((res = check_access(api_path, W_OK)) == api_error::item_not_found) {
|
res = check_access(api_path, W_OK);
|
||||||
|
if (res == api_error::item_not_found) {
|
||||||
res = check_parent_access(api_path, W_OK);
|
res = check_parent_access(api_path, W_OK);
|
||||||
}
|
}
|
||||||
} else if ((res = check_access(api_path, R_OK)) ==
|
} else {
|
||||||
api_error::item_not_found) {
|
res = check_access(api_path, R_OK);
|
||||||
|
if (res == api_error::item_not_found) {
|
||||||
res = check_parent_access(api_path, R_OK);
|
res = check_parent_access(api_path, R_OK);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (res != api_error::success) {
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((is_write_only_op || is_read_write_op) &&
|
||||||
|
not provider_.is_file_writeable(api_path)) {
|
||||||
|
return api_error::permission_denied;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_create_op && is_directory_op) {
|
if (is_create_op && is_directory_op) {
|
||||||
return api_error::invalid_operation;
|
return api_error::invalid_operation;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not is_create_op) {
|
|
||||||
bool dir_exists{};
|
|
||||||
res = provider_.is_directory(api_path, dir_exists);
|
|
||||||
if (res != api_error::success) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool file_exists{};
|
bool file_exists{};
|
||||||
res = provider_.is_file(api_path, file_exists);
|
res = provider_.is_file(api_path, file_exists);
|
||||||
if (res != api_error::success) {
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool dir_exists{};
|
||||||
|
if (not file_exists) {
|
||||||
|
res = provider_.is_directory(api_path, dir_exists);
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_create_op) {
|
||||||
|
if (dir_exists) {
|
||||||
|
return api_error::directory_exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_exclusive && file_exists) {
|
||||||
|
return api_error::item_exists;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (is_directory_op ? file_exists : dir_exists) {
|
||||||
|
return is_directory_op ? api_error::item_exists
|
||||||
|
: api_error::directory_exists;
|
||||||
|
}
|
||||||
|
|
||||||
if (not(is_directory_op ? dir_exists : file_exists)) {
|
if (not(is_directory_op ? dir_exists : file_exists)) {
|
||||||
return (is_directory_op ? api_error::directory_not_found
|
return is_directory_op ? api_error::directory_not_found
|
||||||
: api_error::item_not_found);
|
: api_error::item_not_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((is_exclusive || is_truncate_op) && not file_exists) {
|
||||||
|
return api_error::item_not_found;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,17 +200,16 @@ auto fuse_drive::create_impl(std::string api_path, mode_t mode,
|
|||||||
{
|
{
|
||||||
std::shared_ptr<i_open_file> open_file;
|
std::shared_ptr<i_open_file> open_file;
|
||||||
if (is_create_op) {
|
if (is_create_op) {
|
||||||
const auto now = utils::time::get_time_now();
|
auto now = utils::time::get_time_now();
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
const auto osx_flags = static_cast<std::uint32_t>(file_info->flags);
|
auto osx_flags = static_cast<std::uint32_t>(file_info->flags);
|
||||||
#else // !defined(__APPLE__)
|
#else // !defined(__APPLE__)
|
||||||
const auto osx_flags = 0U;
|
auto osx_flags = 0U;
|
||||||
#endif // defined(__APPLE__)
|
#endif // defined(__APPLE__)
|
||||||
|
|
||||||
auto meta = create_meta_attributes(
|
auto meta = create_meta_attributes(
|
||||||
now, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE, now, now,
|
now, FILE_ATTRIBUTE_ARCHIVE, now, now, is_directory_op,
|
||||||
is_directory_op, get_effective_gid(), "", mode, now, 0U, osx_flags,
|
get_effective_gid(), "", mode, now, 0U, osx_flags, 0U,
|
||||||
0U,
|
|
||||||
utils::path::combine(config_.get_cache_directory(),
|
utils::path::combine(config_.get_cache_directory(),
|
||||||
{utils::create_uuid_string()}),
|
{utils::create_uuid_string()}),
|
||||||
get_effective_uid(), now);
|
get_effective_uid(), now);
|
||||||
@ -196,19 +218,24 @@ auto fuse_drive::create_impl(std::string api_path, mode_t mode,
|
|||||||
if ((res != api_error::item_exists) && (res != api_error::success)) {
|
if ((res != api_error::item_exists) && (res != api_error::success)) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
} else if (((res = fm_->open(api_path, is_directory_op, file_info->flags,
|
} else {
|
||||||
handle, open_file)) != api_error::success)) {
|
res = fm_->open(api_path, is_directory_op, file_info->flags, handle,
|
||||||
|
open_file);
|
||||||
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
file_info->fh = handle;
|
file_info->fh = handle;
|
||||||
if (is_truncate_op) {
|
if (is_truncate_op) {
|
||||||
#if FUSE_USE_VERSION >= 30
|
#if FUSE_USE_VERSION >= 30
|
||||||
if ((res = truncate_impl(api_path, 0, file_info)) != api_error::success) {
|
res = truncate_impl(api_path, 0, file_info);
|
||||||
#else
|
if (res != api_error::success) {
|
||||||
if ((res = ftruncate_impl(api_path, 0, file_info)) != api_error::success) {
|
#else // FUSE_USE_VERSION < 30
|
||||||
#endif
|
res = ftruncate_impl(api_path, 0, file_info);
|
||||||
|
if (res != api_error::success) {
|
||||||
|
#endif // FUSE_USE_VERSION >= 30
|
||||||
fm_->close(handle);
|
fm_->close(handle);
|
||||||
file_info->fh = 0U;
|
file_info->fh = 0U;
|
||||||
errno = std::abs(utils::from_api_error(res));
|
errno = std::abs(utils::from_api_error(res));
|
||||||
@ -277,9 +304,9 @@ auto fuse_drive::fallocate_impl(std::string /*api_path*/, int mode,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((res = check_open_flags(
|
res = check_open_flags(open_file->get_open_data(file_info->fh),
|
||||||
open_file->get_open_data(file_info->fh), O_WRONLY | O_APPEND,
|
O_WRONLY | O_APPEND, api_error::invalid_handle);
|
||||||
api_error::invalid_handle)) != api_error::success) {
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,7 +350,7 @@ auto fuse_drive::fallocate_impl(std::string /*api_path*/, int mode,
|
|||||||
static_cast<std::uint64_t>(offset + length), allocator);
|
static_cast<std::uint64_t>(offset + length), allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto fuse_drive::fgetattr_impl(std::string api_path, struct stat *st,
|
auto fuse_drive::fgetattr_impl(std::string api_path, struct stat *unix_st,
|
||||||
struct fuse_file_info *file_info) -> api_error {
|
struct fuse_file_info *file_info) -> api_error {
|
||||||
std::shared_ptr<i_open_file> open_file;
|
std::shared_ptr<i_open_file> open_file;
|
||||||
if (not fm_->get_open_file(file_info->fh, false, open_file)) {
|
if (not fm_->get_open_file(file_info->fh, false, open_file)) {
|
||||||
@ -342,7 +369,7 @@ auto fuse_drive::fgetattr_impl(std::string api_path, struct stat *st,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
fuse_drive_base::populate_stat(api_path, open_file->get_file_size(), meta,
|
fuse_drive_base::populate_stat(api_path, open_file->get_file_size(), meta,
|
||||||
directory, provider_, st);
|
directory, provider_, unix_st);
|
||||||
|
|
||||||
return api_error::success;
|
return api_error::success;
|
||||||
}
|
}
|
||||||
@ -389,7 +416,7 @@ api_error fuse_drive::ftruncate_impl(std::string /*api_path*/, off_t size,
|
|||||||
return api_error::invalid_handle;
|
return api_error::invalid_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto res = check_writeable(f->get_open_data(file_info->fh),
|
auto res = check_writeable(f->get_open_data(file_info->fh),
|
||||||
api_error::invalid_handle);
|
api_error::invalid_handle);
|
||||||
if (res != api_error::success) {
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
@ -441,7 +468,7 @@ auto fuse_drive::get_item_meta(const std::string &api_path,
|
|||||||
const std::string &name,
|
const std::string &name,
|
||||||
std::string &value) const -> api_error {
|
std::string &value) const -> api_error {
|
||||||
api_meta_map meta{};
|
api_meta_map meta{};
|
||||||
const auto ret = get_item_meta(api_path, meta);
|
auto ret = get_item_meta(api_path, meta);
|
||||||
if (ret == api_error::success) {
|
if (ret == api_error::success) {
|
||||||
value = meta[name];
|
value = meta[name];
|
||||||
}
|
}
|
||||||
@ -450,14 +477,14 @@ auto fuse_drive::get_item_meta(const std::string &api_path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if FUSE_USE_VERSION >= 30
|
#if FUSE_USE_VERSION >= 30
|
||||||
auto fuse_drive::getattr_impl(std::string api_path, struct stat *st,
|
auto fuse_drive::getattr_impl(std::string api_path, struct stat *unix_st,
|
||||||
struct fuse_file_info * /*file_info*/)
|
struct fuse_file_info * /*file_info*/)
|
||||||
-> api_error {
|
-> api_error {
|
||||||
#else
|
#else
|
||||||
auto fuse_drive::getattr_impl(std::string api_path,
|
auto fuse_drive::getattr_impl(std::string api_path,
|
||||||
struct stat *st) -> api_error {
|
struct stat *unix_st) -> api_error {
|
||||||
#endif
|
#endif
|
||||||
const auto parent = utils::path::get_parent_api_path(api_path);
|
auto parent = utils::path::get_parent_api_path(api_path);
|
||||||
|
|
||||||
auto res = check_parent_access(api_path, X_OK);
|
auto res = check_parent_access(api_path, X_OK);
|
||||||
if (res != api_error::success) {
|
if (res != api_error::success) {
|
||||||
@ -467,16 +494,17 @@ auto fuse_drive::getattr_impl(std::string api_path,
|
|||||||
auto found = false;
|
auto found = false;
|
||||||
directory_cache_->execute_action(parent, [&](directory_iterator &iter) {
|
directory_cache_->execute_action(parent, [&](directory_iterator &iter) {
|
||||||
directory_item dir_item{};
|
directory_item dir_item{};
|
||||||
if ((found = (iter.get_directory_item(api_path, dir_item) ==
|
found = (iter.get_directory_item(api_path, dir_item) == api_error::success);
|
||||||
api_error::success))) {
|
if (found) {
|
||||||
fuse_drive_base::populate_stat(api_path, dir_item.size, dir_item.meta,
|
fuse_drive_base::populate_stat(api_path, dir_item.size, dir_item.meta,
|
||||||
dir_item.directory, provider_, st);
|
dir_item.directory, provider_, unix_st);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (not found) {
|
if (not found) {
|
||||||
api_meta_map meta{};
|
api_meta_map meta{};
|
||||||
if ((res = provider_.get_item_meta(api_path, meta)) != api_error::success) {
|
res = provider_.get_item_meta(api_path, meta);
|
||||||
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -487,7 +515,7 @@ auto fuse_drive::getattr_impl(std::string api_path,
|
|||||||
}
|
}
|
||||||
fuse_drive_base::populate_stat(api_path,
|
fuse_drive_base::populate_stat(api_path,
|
||||||
utils::string::to_uint64(meta[META_SIZE]),
|
utils::string::to_uint64(meta[META_SIZE]),
|
||||||
meta, directory, provider_, st);
|
meta, directory, provider_, unix_st);
|
||||||
}
|
}
|
||||||
|
|
||||||
return api_error::success;
|
return api_error::success;
|
||||||
@ -560,11 +588,9 @@ void *fuse_drive::init_impl(struct fuse_conn_info *conn) {
|
|||||||
event_system::instance().start();
|
event_system::instance().start();
|
||||||
was_mounted_ = true;
|
was_mounted_ = true;
|
||||||
|
|
||||||
polling::instance().start(&config_);
|
|
||||||
|
|
||||||
fm_ = std::make_unique<file_manager>(config_, provider_);
|
fm_ = std::make_unique<file_manager>(config_, provider_);
|
||||||
server_ = std::make_unique<full_server>(config_, provider_, *fm_);
|
server_ = std::make_unique<full_server>(config_, provider_, *fm_);
|
||||||
if (not provider_.is_direct_only()) {
|
if (not provider_.is_read_only()) {
|
||||||
eviction_ = std::make_unique<eviction>(provider_, config_, *fm_);
|
eviction_ = std::make_unique<eviction>(provider_, config_, *fm_);
|
||||||
}
|
}
|
||||||
directory_cache_ = std::make_unique<directory_cache>();
|
directory_cache_ = std::make_unique<directory_cache>();
|
||||||
@ -586,7 +612,7 @@ void *fuse_drive::init_impl(struct fuse_conn_info *conn) {
|
|||||||
eviction_->start();
|
eviction_->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config_.get_enable_remote_mount()) {
|
if (config_.get_remote_mount().enable) {
|
||||||
remote_server_ = std::make_unique<remote_fuse::remote_server>(
|
remote_server_ = std::make_unique<remote_fuse::remote_server>(
|
||||||
config_, *this, get_mount_location());
|
config_, *this, get_mount_location());
|
||||||
}
|
}
|
||||||
@ -594,6 +620,9 @@ void *fuse_drive::init_impl(struct fuse_conn_info *conn) {
|
|||||||
if (not lock_data_.set_mount_state(true, get_mount_location(), getpid())) {
|
if (not lock_data_.set_mount_state(true, get_mount_location(), getpid())) {
|
||||||
utils::error::raise_error(function_name, "failed to set mount state");
|
utils::error::raise_error(function_name, "failed to set mount state");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
polling::instance().start(&config_);
|
||||||
|
|
||||||
event_system::instance().raise<drive_mounted>(get_mount_location());
|
event_system::instance().raise<drive_mounted>(get_mount_location());
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
utils::error::raise_error(function_name, e, "exception during fuse init");
|
utils::error::raise_error(function_name, e, "exception during fuse init");
|
||||||
@ -618,7 +647,7 @@ auto fuse_drive::mkdir_impl(std::string api_path, mode_t mode) -> api_error {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto now = utils::time::get_time_now();
|
auto now = utils::time::get_time_now();
|
||||||
auto meta = create_meta_attributes(now, FILE_ATTRIBUTE_DIRECTORY, now, now,
|
auto meta = create_meta_attributes(now, FILE_ATTRIBUTE_DIRECTORY, now, now,
|
||||||
true, get_effective_gid(), "", mode, now,
|
true, get_effective_gid(), "", mode, now,
|
||||||
0U, 0U, 0U, "", get_effective_uid(), now);
|
0U, 0U, 0U, "", get_effective_uid(), now);
|
||||||
@ -651,20 +680,21 @@ void fuse_drive::notify_fuse_main_exit(int &ret) {
|
|||||||
|
|
||||||
auto fuse_drive::open_impl(std::string api_path,
|
auto fuse_drive::open_impl(std::string api_path,
|
||||||
struct fuse_file_info *file_info) -> api_error {
|
struct fuse_file_info *file_info) -> api_error {
|
||||||
|
|
||||||
file_info->flags &= (~O_CREAT);
|
file_info->flags &= (~O_CREAT);
|
||||||
return create_impl(api_path, 0, file_info);
|
return create_impl(api_path, 0, file_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto fuse_drive::opendir_impl(std::string api_path,
|
auto fuse_drive::opendir_impl(std::string api_path,
|
||||||
struct fuse_file_info *file_info) -> api_error {
|
struct fuse_file_info *file_info) -> api_error {
|
||||||
const auto mask =
|
auto mask = (O_RDONLY != (file_info->flags & O_ACCMODE) ? W_OK : R_OK) | X_OK;
|
||||||
(O_RDONLY != (file_info->flags & O_ACCMODE) ? W_OK : R_OK) | X_OK;
|
|
||||||
auto res = check_access(api_path, mask);
|
auto res = check_access(api_path, mask);
|
||||||
if (res != api_error::success) {
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((res = check_parent_access(api_path, mask)) != api_error::success) {
|
res = check_parent_access(api_path, mask);
|
||||||
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -677,9 +707,14 @@ auto fuse_drive::opendir_impl(std::string api_path,
|
|||||||
return api_error::directory_not_found;
|
return api_error::directory_not_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((file_info->flags & O_APPEND) == O_APPEND ||
|
||||||
|
(file_info->flags & O_EXCL) == O_EXCL) {
|
||||||
|
return api_error::directory_exists;
|
||||||
|
}
|
||||||
|
|
||||||
directory_item_list list{};
|
directory_item_list list{};
|
||||||
if ((res = provider_.get_directory_items(api_path, list)) !=
|
res = provider_.get_directory_items(api_path, list);
|
||||||
api_error::success) {
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -707,7 +742,8 @@ auto fuse_drive::read_impl(std::string api_path, char *buffer, size_t read_size,
|
|||||||
data_buffer data;
|
data_buffer data;
|
||||||
res =
|
res =
|
||||||
open_file->read(read_size, static_cast<std::uint64_t>(read_offset), data);
|
open_file->read(read_size, static_cast<std::uint64_t>(read_offset), data);
|
||||||
if ((bytes_read = data.size()) != 0U) {
|
bytes_read = data.size();
|
||||||
|
if (bytes_read != 0U) {
|
||||||
std::memcpy(buffer, data.data(), data.size());
|
std::memcpy(buffer, data.data(), data.size());
|
||||||
data.clear();
|
data.clear();
|
||||||
update_accessed_time(api_path);
|
update_accessed_time(api_path);
|
||||||
@ -737,13 +773,14 @@ auto fuse_drive::readdir_impl(std::string api_path, void *buf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (res == api_error::success) {
|
while (res == api_error::success) {
|
||||||
res = (iter->fill_buffer(
|
res =
|
||||||
|
(iter->fill_buffer(
|
||||||
static_cast<remote::file_offset>(offset++), fuse_fill_dir, buf,
|
static_cast<remote::file_offset>(offset++), fuse_fill_dir, buf,
|
||||||
[this](const std::string &cur_api_path,
|
[this](const std::string &cur_api_path,
|
||||||
std::uint64_t cur_file_size, const api_meta_map &meta,
|
std::uint64_t cur_file_size, const api_meta_map &meta,
|
||||||
bool directory, struct stat *st) {
|
bool directory, struct stat *unix_st) {
|
||||||
fuse_drive_base::populate_stat(cur_api_path, cur_file_size,
|
fuse_drive_base::populate_stat(cur_api_path, cur_file_size, meta,
|
||||||
meta, directory, provider_, st);
|
directory, provider_, unix_st);
|
||||||
}) == 0)
|
}) == 0)
|
||||||
? api_error::success
|
? api_error::success
|
||||||
: api_error::os_error;
|
: api_error::os_error;
|
||||||
@ -776,7 +813,7 @@ auto fuse_drive::releasedir_impl(
|
|||||||
|
|
||||||
auto fuse_drive::rename_directory(const std::string &from_api_path,
|
auto fuse_drive::rename_directory(const std::string &from_api_path,
|
||||||
const std::string &to_api_path) -> int {
|
const std::string &to_api_path) -> int {
|
||||||
const auto res = fm_->rename_directory(from_api_path, to_api_path);
|
auto res = fm_->rename_directory(from_api_path, to_api_path);
|
||||||
errno = std::abs(utils::from_api_error(res));
|
errno = std::abs(utils::from_api_error(res));
|
||||||
return (res == api_error::success) ? 0 : -1;
|
return (res == api_error::success) ? 0 : -1;
|
||||||
}
|
}
|
||||||
@ -784,7 +821,7 @@ auto fuse_drive::rename_directory(const std::string &from_api_path,
|
|||||||
auto fuse_drive::rename_file(const std::string &from_api_path,
|
auto fuse_drive::rename_file(const std::string &from_api_path,
|
||||||
const std::string &to_api_path,
|
const std::string &to_api_path,
|
||||||
bool overwrite) -> int {
|
bool overwrite) -> int {
|
||||||
const auto res = fm_->rename_file(from_api_path, to_api_path, overwrite);
|
auto res = fm_->rename_file(from_api_path, to_api_path, overwrite);
|
||||||
errno = std::abs(utils::from_api_error(res));
|
errno = std::abs(utils::from_api_error(res));
|
||||||
return (res == api_error::success) ? 0 : -1;
|
return (res == api_error::success) ? 0 : -1;
|
||||||
}
|
}
|
||||||
@ -801,8 +838,8 @@ auto fuse_drive::rename_impl(std::string from_api_path,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((res = check_parent_access(from_api_path, W_OK | X_OK)) !=
|
res = check_parent_access(from_api_path, W_OK | X_OK);
|
||||||
api_error::success) {
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -829,7 +866,8 @@ auto fuse_drive::rmdir_impl(std::string api_path) -> api_error {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((res = provider_.remove_directory(api_path)) != api_error::success) {
|
res = provider_.remove_directory(api_path);
|
||||||
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -854,42 +892,48 @@ auto fuse_drive::getxattr_common(std::string api_path, const char *name,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((res = check_parent_access(api_path, X_OK)) != api_error::success) {
|
res = check_parent_access(api_path, X_OK);
|
||||||
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
api_meta_map meta;
|
api_meta_map meta;
|
||||||
auto found = false;
|
auto found{false};
|
||||||
directory_cache_->execute_action(
|
directory_cache_->execute_action(
|
||||||
utils::path::get_parent_api_path(api_path),
|
utils::path::get_parent_api_path(api_path),
|
||||||
[&](directory_iterator &iterator) {
|
[&](directory_iterator &iterator) {
|
||||||
directory_item dir_item{};
|
directory_item dir_item{};
|
||||||
if ((found = (iterator.get_directory_item(api_path, dir_item) ==
|
found = (iterator.get_directory_item(api_path, dir_item) ==
|
||||||
api_error::success))) {
|
api_error::success);
|
||||||
|
if (found) {
|
||||||
meta = dir_item.meta;
|
meta = dir_item.meta;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (found ||
|
res = found ? api_error::success : provider_.get_item_meta(api_path, meta);
|
||||||
((res = provider_.get_item_meta(api_path, meta)) == api_error::success)) {
|
if (res != api_error::success) {
|
||||||
res = api_error::xattr_not_found;
|
return res;
|
||||||
if (meta.find(attribute_name) != meta.end()) {
|
|
||||||
const auto data = macaron::Base64::Decode(meta[attribute_name]);
|
|
||||||
if ((position == nullptr) || (*position < data.size())) {
|
|
||||||
res = api_error::success;
|
|
||||||
attribute_size = static_cast<int>(data.size());
|
|
||||||
if (size != 0U) {
|
|
||||||
res = api_error::xattr_buffer_small;
|
|
||||||
if (size >= data.size()) {
|
|
||||||
memcpy(value, data.data(), data.size());
|
|
||||||
return api_error::success;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
if (meta.find(attribute_name) == meta.end()) {
|
||||||
|
return api_error::xattr_not_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto data = macaron::Base64::Decode(meta.at(attribute_name));
|
||||||
|
if ((position == nullptr) || (*position < data.size())) {
|
||||||
|
attribute_size = static_cast<int>(data.size());
|
||||||
|
if (size == 0U) {
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size < data.size()) {
|
||||||
|
return api_error::xattr_buffer_small;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::memcpy(value, data.data(), data.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
return api_error::success;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
@ -910,7 +954,7 @@ auto fuse_drive::getxattr_impl(std::string api_path, const char *name,
|
|||||||
auto fuse_drive::listxattr_impl(std::string api_path, char *buffer, size_t size,
|
auto fuse_drive::listxattr_impl(std::string api_path, char *buffer, size_t size,
|
||||||
int &required_size,
|
int &required_size,
|
||||||
bool &return_size) -> api_error {
|
bool &return_size) -> api_error {
|
||||||
const auto check_size = (size == 0);
|
auto check_size = (size == 0);
|
||||||
|
|
||||||
auto res = check_parent_access(api_path, X_OK);
|
auto res = check_parent_access(api_path, X_OK);
|
||||||
if (res != api_error::success) {
|
if (res != api_error::success) {
|
||||||
@ -918,14 +962,15 @@ auto fuse_drive::listxattr_impl(std::string api_path, char *buffer, size_t size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
api_meta_map meta;
|
api_meta_map meta;
|
||||||
if ((res = provider_.get_item_meta(api_path, meta)) == api_error::success) {
|
res = provider_.get_item_meta(api_path, meta);
|
||||||
|
if (res == api_error::success) {
|
||||||
for (auto &&meta_item : meta) {
|
for (auto &&meta_item : meta) {
|
||||||
if (utils::collection::excludes(META_USED_NAMES, meta_item.first)) {
|
if (utils::collection::excludes(META_USED_NAMES, meta_item.first)) {
|
||||||
auto attribute_name = meta_item.first;
|
auto attribute_name = meta_item.first;
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
if (attribute_name != G_KAUTH_FILESEC_XATTR) {
|
if (attribute_name != G_KAUTH_FILESEC_XATTR) {
|
||||||
#endif
|
#endif
|
||||||
const auto attribute_name_size = strlen(attribute_name.c_str()) + 1U;
|
auto attribute_name_size = strlen(attribute_name.c_str()) + 1U;
|
||||||
if (size >= attribute_name_size) {
|
if (size >= attribute_name_size) {
|
||||||
std::memcpy(&buffer[required_size], attribute_name.data(),
|
std::memcpy(&buffer[required_size], attribute_name.data(),
|
||||||
attribute_name_size);
|
attribute_name_size);
|
||||||
@ -992,7 +1037,7 @@ auto fuse_drive::setxattr_impl(std::string api_path, const char *name,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto attribute_namespace =
|
auto attribute_namespace =
|
||||||
utils::string::contains(attribute_name, ".")
|
utils::string::contains(attribute_name, ".")
|
||||||
? utils::string::split(attribute_name, '.', false)[0U]
|
? utils::string::split(attribute_name, '.', false)[0U]
|
||||||
: "";
|
: "";
|
||||||
@ -1011,15 +1056,18 @@ auto fuse_drive::setxattr_impl(std::string api_path, const char *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
api_meta_map meta;
|
api_meta_map meta;
|
||||||
if ((res = provider_.get_item_meta(api_path, meta)) != api_error::success) {
|
res = provider_.get_item_meta(api_path, meta);
|
||||||
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((res = check_parent_access(api_path, X_OK)) != api_error::success) {
|
res = check_parent_access(api_path, X_OK);
|
||||||
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((res = check_owner(meta)) != api_error::success) {
|
res = check_owner(meta);
|
||||||
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1157,7 +1205,7 @@ auto fuse_drive::setbkuptime_impl(
|
|||||||
std::string api_path, const struct timespec *bkuptime) -> api_error {
|
std::string api_path, const struct timespec *bkuptime) -> api_error {
|
||||||
return check_and_perform(
|
return check_and_perform(
|
||||||
api_path, X_OK, [&](api_meta_map &meta) -> api_error {
|
api_path, X_OK, [&](api_meta_map &meta) -> api_error {
|
||||||
const auto nanos = bkuptime->tv_nsec +
|
auto nanos = bkuptime->tv_nsec +
|
||||||
(bkuptime->tv_nsec * utils::time::NANOS_PER_SECOND);
|
(bkuptime->tv_nsec * utils::time::NANOS_PER_SECOND);
|
||||||
return provider_.set_item_meta(api_path, META_BACKUP,
|
return provider_.set_item_meta(api_path, META_BACKUP,
|
||||||
std::to_string(nanos));
|
std::to_string(nanos));
|
||||||
@ -1168,7 +1216,7 @@ auto fuse_drive::setchgtime_impl(std::string api_path,
|
|||||||
const struct timespec *chgtime) -> api_error {
|
const struct timespec *chgtime) -> api_error {
|
||||||
return check_and_perform(
|
return check_and_perform(
|
||||||
api_path, X_OK, [&](api_meta_map &meta) -> api_error {
|
api_path, X_OK, [&](api_meta_map &meta) -> api_error {
|
||||||
const auto nanos = chgtime->tv_nsec +
|
auto nanos = chgtime->tv_nsec +
|
||||||
(chgtime->tv_nsec * utils::time::NANOS_PER_SECOND);
|
(chgtime->tv_nsec * utils::time::NANOS_PER_SECOND);
|
||||||
return provider_.set_item_meta(api_path, META_CHANGED,
|
return provider_.set_item_meta(api_path, META_CHANGED,
|
||||||
std::to_string(nanos));
|
std::to_string(nanos));
|
||||||
@ -1179,7 +1227,7 @@ auto fuse_drive::setcrtime_impl(std::string api_path,
|
|||||||
const struct timespec *crtime) -> api_error {
|
const struct timespec *crtime) -> api_error {
|
||||||
return check_and_perform(
|
return check_and_perform(
|
||||||
api_path, X_OK, [&](api_meta_map &meta) -> api_error {
|
api_path, X_OK, [&](api_meta_map &meta) -> api_error {
|
||||||
const auto nanos =
|
auto nanos =
|
||||||
crtime->tv_nsec + (crtime->tv_nsec * utils::time::NANOS_PER_SECOND);
|
crtime->tv_nsec + (crtime->tv_nsec * utils::time::NANOS_PER_SECOND);
|
||||||
return provider_.set_item_meta(api_path, META_CREATION,
|
return provider_.set_item_meta(api_path, META_CREATION,
|
||||||
std::to_string(nanos));
|
std::to_string(nanos));
|
||||||
@ -1196,9 +1244,9 @@ auto fuse_drive::statfs_x_impl(std::string /*api_path*/,
|
|||||||
return api_error::os_error;
|
return api_error::os_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto total_bytes = provider_.get_total_drive_space();
|
auto total_bytes = provider_.get_total_drive_space();
|
||||||
const auto total_used = provider_.get_used_drive_space();
|
auto total_used = provider_.get_used_drive_space();
|
||||||
const auto used_blocks = utils::divide_with_ceiling(
|
auto used_blocks = utils::divide_with_ceiling(
|
||||||
total_used, static_cast<std::uint64_t>(stbuf->f_bsize));
|
total_used, static_cast<std::uint64_t>(stbuf->f_bsize));
|
||||||
stbuf->f_blocks = utils::divide_with_ceiling(
|
stbuf->f_blocks = utils::divide_with_ceiling(
|
||||||
total_bytes, static_cast<std::uint64_t>(stbuf->f_bsize));
|
total_bytes, static_cast<std::uint64_t>(stbuf->f_bsize));
|
||||||
@ -1222,10 +1270,9 @@ auto fuse_drive::statfs_impl(std::string /*api_path*/,
|
|||||||
return api_error::os_error;
|
return api_error::os_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto total_bytes = provider_.get_total_drive_space();
|
auto total_bytes = provider_.get_total_drive_space();
|
||||||
const auto total_used = provider_.get_used_drive_space();
|
auto total_used = provider_.get_used_drive_space();
|
||||||
const auto used_blocks =
|
auto used_blocks = utils::divide_with_ceiling(total_used, stbuf->f_frsize);
|
||||||
utils::divide_with_ceiling(total_used, stbuf->f_frsize);
|
|
||||||
stbuf->f_files = 4294967295;
|
stbuf->f_files = 4294967295;
|
||||||
stbuf->f_blocks = utils::divide_with_ceiling(total_bytes, stbuf->f_frsize);
|
stbuf->f_blocks = utils::divide_with_ceiling(total_bytes, stbuf->f_frsize);
|
||||||
stbuf->f_bavail = stbuf->f_bfree =
|
stbuf->f_bavail = stbuf->f_bfree =
|
||||||
@ -1250,12 +1297,12 @@ auto fuse_drive::truncate_impl(std::string api_path, off_t size) -> api_error {
|
|||||||
if (res != api_error::success) {
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
res = check_parent_access(api_path, X_OK);
|
||||||
if ((res = check_parent_access(api_path, X_OK)) != api_error::success) {
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
res = check_access(api_path, W_OK);
|
||||||
if ((res = check_access(api_path, W_OK)) != api_error::success) {
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1263,11 +1310,15 @@ auto fuse_drive::truncate_impl(std::string api_path, off_t size) -> api_error {
|
|||||||
{
|
{
|
||||||
open_file_data ofd{O_RDWR};
|
open_file_data ofd{O_RDWR};
|
||||||
std::shared_ptr<i_open_file> open_file;
|
std::shared_ptr<i_open_file> open_file;
|
||||||
if ((res = fm_->open(api_path, false, ofd, handle, open_file)) !=
|
res = fm_->open(api_path, false, ofd, handle, open_file);
|
||||||
api_error::success) {
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (not fm_->get_open_file(handle, true, open_file)) {
|
||||||
|
return api_error::invalid_handle;
|
||||||
|
}
|
||||||
|
|
||||||
res = open_file->resize(static_cast<std::uint64_t>(size));
|
res = open_file->resize(static_cast<std::uint64_t>(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1307,7 +1358,8 @@ auto fuse_drive::utimens_impl(std::string api_path,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((res = check_owner(meta)) != api_error::success) {
|
res = check_owner(meta);
|
||||||
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include "drives/fuse/fuse_drive_base.hpp"
|
#include "drives/fuse/fuse_drive_base.hpp"
|
||||||
|
|
||||||
|
#include "events/events.hpp"
|
||||||
#include "platform/platform.hpp"
|
#include "platform/platform.hpp"
|
||||||
#include "providers/i_provider.hpp"
|
#include "providers/i_provider.hpp"
|
||||||
#include "utils/common.hpp"
|
#include "utils/common.hpp"
|
||||||
@ -35,8 +36,10 @@ auto fuse_drive_base::access_impl(std::string api_path, int mask) -> api_error {
|
|||||||
|
|
||||||
auto fuse_drive_base::check_access(const std::string &api_path,
|
auto fuse_drive_base::check_access(const std::string &api_path,
|
||||||
int mask) const -> api_error {
|
int mask) const -> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
api_meta_map meta;
|
api_meta_map meta;
|
||||||
const auto res = get_item_meta(api_path, meta);
|
auto res = get_item_meta(api_path, meta);
|
||||||
if (res != api_error::success) {
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -48,7 +51,7 @@ auto fuse_drive_base::check_access(const std::string &api_path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Always allow forced user
|
// Always allow forced user
|
||||||
if (forced_uid_.has_value() || (current_uid == get_effective_uid())) {
|
if (forced_uid_.has_value() && (current_uid == get_effective_uid())) {
|
||||||
return api_error::success;
|
return api_error::success;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,9 +60,9 @@ auto fuse_drive_base::check_access(const std::string &api_path,
|
|||||||
return api_error::success;
|
return api_error::success;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto effective_uid =
|
auto effective_uid =
|
||||||
(forced_uid_.has_value() ? forced_uid_.value() : get_uid_from_meta(meta));
|
(forced_uid_.has_value() ? forced_uid_.value() : get_uid_from_meta(meta));
|
||||||
const auto effective_gid =
|
auto effective_gid =
|
||||||
(forced_gid_.has_value() ? forced_gid_.value() : get_gid_from_meta(meta));
|
(forced_gid_.has_value() ? forced_gid_.value() : get_gid_from_meta(meta));
|
||||||
|
|
||||||
// Create file mode
|
// Create file mode
|
||||||
@ -73,10 +76,9 @@ auto fuse_drive_base::check_access(const std::string &api_path,
|
|||||||
if (current_uid == effective_uid) {
|
if (current_uid == effective_uid) {
|
||||||
active_mask |= S_IRWXU;
|
active_mask |= S_IRWXU;
|
||||||
}
|
}
|
||||||
if (get_current_gid() == effective_gid) {
|
|
||||||
active_mask |= S_IRWXG;
|
if (get_current_gid() == effective_gid ||
|
||||||
}
|
utils::is_uid_member_of_group(current_uid, effective_gid)) {
|
||||||
if (utils::is_uid_member_of_group(current_uid, effective_gid)) {
|
|
||||||
active_mask |= S_IRWXG;
|
active_mask |= S_IRWXG;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,7 +88,7 @@ auto fuse_drive_base::check_access(const std::string &api_path,
|
|||||||
// Check allow execute
|
// Check allow execute
|
||||||
if ((mask & X_OK) == X_OK) {
|
if ((mask & X_OK) == X_OK) {
|
||||||
if ((effective_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) {
|
if ((effective_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) {
|
||||||
return api_error::permission_denied;
|
return api_error::access_denied;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,8 +176,8 @@ auto fuse_drive_base::check_parent_access(const std::string &api_path,
|
|||||||
for (auto parent = utils::path::get_parent_path(api_path);
|
for (auto parent = utils::path::get_parent_path(api_path);
|
||||||
(ret == api_error::success) && not parent.empty();
|
(ret == api_error::success) && not parent.empty();
|
||||||
parent = utils::path::get_parent_path(parent)) {
|
parent = utils::path::get_parent_path(parent)) {
|
||||||
if (((ret = check_access(parent, X_OK)) == api_error::success) &&
|
ret = check_access(parent, X_OK);
|
||||||
(parent == "/")) {
|
if ((ret == api_error::success) && (parent == "/")) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,7 +196,7 @@ auto fuse_drive_base::check_parent_access(const std::string &api_path,
|
|||||||
|
|
||||||
auto fuse_drive_base::check_readable(int flags,
|
auto fuse_drive_base::check_readable(int flags,
|
||||||
const api_error &fail_error) -> api_error {
|
const api_error &fail_error) -> api_error {
|
||||||
const auto mode = (flags & O_ACCMODE);
|
auto mode = (flags & O_ACCMODE);
|
||||||
return ((mode == O_WRONLY) ? fail_error : api_error::success);
|
return ((mode == O_WRONLY) ? fail_error : api_error::success);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,7 +322,7 @@ void fuse_drive_base::populate_stat(const std::string &api_path,
|
|||||||
st->st_size = static_cast<off_t>(size_or_count);
|
st->st_size = static_cast<off_t>(size_or_count);
|
||||||
static const auto block_size_stat = static_cast<std::uint64_t>(512U);
|
static const auto block_size_stat = static_cast<std::uint64_t>(512U);
|
||||||
static const auto block_size = static_cast<std::uint64_t>(4096U);
|
static const auto block_size = static_cast<std::uint64_t>(4096U);
|
||||||
const auto size = utils::divide_with_ceiling(
|
auto size = utils::divide_with_ceiling(
|
||||||
static_cast<std::uint64_t>(st->st_size), block_size) *
|
static_cast<std::uint64_t>(st->st_size), block_size) *
|
||||||
block_size;
|
block_size;
|
||||||
st->st_blocks = static_cast<blkcnt_t>(
|
st->st_blocks = static_cast<blkcnt_t>(
|
||||||
|
@ -27,12 +27,7 @@
|
|||||||
|
|
||||||
namespace repertory::remote_fuse {
|
namespace repertory::remote_fuse {
|
||||||
remote_client::remote_client(const app_config &config)
|
remote_client::remote_client(const app_config &config)
|
||||||
: config_(config),
|
: config_(config), packet_client_(config.get_remote_config()) {}
|
||||||
packet_client_(
|
|
||||||
config.get_remote_host_name_or_ip(),
|
|
||||||
config.get_remote_max_connections(), config.get_remote_port(),
|
|
||||||
config.get_remote_receive_timeout_secs(),
|
|
||||||
config.get_remote_send_timeout_secs(), config.get_remote_token()) {}
|
|
||||||
|
|
||||||
auto remote_client::fuse_access(const char *path, const std::int32_t &mask)
|
auto remote_client::fuse_access(const char *path, const std::int32_t &mask)
|
||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
|
@ -40,8 +40,8 @@
|
|||||||
#include "utils/utils.hpp"
|
#include "utils/utils.hpp"
|
||||||
|
|
||||||
namespace repertory::remote_fuse {
|
namespace repertory::remote_fuse {
|
||||||
auto remote_fuse_drive::access_impl(std::string api_path, int mask)
|
auto remote_fuse_drive::access_impl(std::string api_path,
|
||||||
-> api_error {
|
int mask) -> api_error {
|
||||||
return utils::to_api_error(
|
return utils::to_api_error(
|
||||||
remote_instance_->fuse_access(api_path.c_str(), mask));
|
remote_instance_->fuse_access(api_path.c_str(), mask));
|
||||||
}
|
}
|
||||||
@ -59,8 +59,8 @@ auto remote_fuse_drive::chmod_impl(std::string api_path, mode_t mode,
|
|||||||
struct fuse_file_info * /*f_info*/)
|
struct fuse_file_info * /*f_info*/)
|
||||||
-> api_error {
|
-> api_error {
|
||||||
#else
|
#else
|
||||||
auto remote_fuse_drive::chmod_impl(std::string api_path, mode_t mode)
|
auto remote_fuse_drive::chmod_impl(std::string api_path,
|
||||||
-> api_error {
|
mode_t mode) -> api_error {
|
||||||
#endif
|
#endif
|
||||||
return utils::to_api_error(remote_instance_->fuse_chmod(
|
return utils::to_api_error(remote_instance_->fuse_chmod(
|
||||||
api_path.c_str(), static_cast<remote::file_mode>(mode)));
|
api_path.c_str(), static_cast<remote::file_mode>(mode)));
|
||||||
@ -71,8 +71,8 @@ auto remote_fuse_drive::chown_impl(std::string api_path, uid_t uid, gid_t gid,
|
|||||||
struct fuse_file_info * /*f_info*/)
|
struct fuse_file_info * /*f_info*/)
|
||||||
-> api_error {
|
-> api_error {
|
||||||
#else
|
#else
|
||||||
auto remote_fuse_drive::chown_impl(std::string api_path, uid_t uid, gid_t gid)
|
auto remote_fuse_drive::chown_impl(std::string api_path, uid_t uid,
|
||||||
-> api_error {
|
gid_t gid) -> api_error {
|
||||||
#endif
|
#endif
|
||||||
return utils::to_api_error(
|
return utils::to_api_error(
|
||||||
remote_instance_->fuse_chown(api_path.c_str(), uid, gid));
|
remote_instance_->fuse_chown(api_path.c_str(), uid, gid));
|
||||||
@ -116,10 +116,9 @@ void remote_fuse_drive::destroy_impl(void *ptr) {
|
|||||||
fuse_base::destroy_impl(ptr);
|
fuse_base::destroy_impl(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto remote_fuse_drive::fgetattr_impl(std::string api_path,
|
auto remote_fuse_drive::fgetattr_impl(
|
||||||
struct stat *unix_st,
|
std::string api_path, struct stat *unix_st,
|
||||||
struct fuse_file_info *f_info)
|
struct fuse_file_info *f_info) -> api_error {
|
||||||
-> api_error {
|
|
||||||
remote::stat r_stat{};
|
remote::stat r_stat{};
|
||||||
auto directory = false;
|
auto directory = false;
|
||||||
|
|
||||||
@ -180,8 +179,8 @@ auto remote_fuse_drive::getattr_impl(std::string api_path, struct stat *unix_st,
|
|||||||
struct fuse_file_info * /*f_info*/)
|
struct fuse_file_info * /*f_info*/)
|
||||||
-> api_error {
|
-> api_error {
|
||||||
#else
|
#else
|
||||||
auto remote_fuse_drive::getattr_impl(std::string api_path, struct stat *unix_st)
|
auto remote_fuse_drive::getattr_impl(std::string api_path,
|
||||||
-> api_error {
|
struct stat *unix_st) -> api_error {
|
||||||
#endif
|
#endif
|
||||||
bool directory = false;
|
bool directory = false;
|
||||||
remote::stat r_stat{};
|
remote::stat r_stat{};
|
||||||
@ -264,8 +263,8 @@ auto remote_fuse_drive::init_impl(struct fuse_conn_info *conn) -> void * {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto remote_fuse_drive::mkdir_impl(std::string api_path, mode_t mode)
|
auto remote_fuse_drive::mkdir_impl(std::string api_path,
|
||||||
-> api_error {
|
mode_t mode) -> api_error {
|
||||||
return utils::to_api_error(remote_instance_->fuse_mkdir(
|
return utils::to_api_error(remote_instance_->fuse_mkdir(
|
||||||
api_path.c_str(), static_cast<remote::file_mode>(mode)));
|
api_path.c_str(), static_cast<remote::file_mode>(mode)));
|
||||||
}
|
}
|
||||||
@ -287,9 +286,12 @@ auto remote_fuse_drive::open_impl(std::string api_path,
|
|||||||
f_info->fh));
|
f_info->fh));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto remote_fuse_drive::opendir_impl(std::string api_path,
|
auto remote_fuse_drive::opendir_impl(
|
||||||
struct fuse_file_info *f_info)
|
std::string api_path, struct fuse_file_info *f_info) -> api_error {
|
||||||
-> api_error {
|
if ((f_info->flags & O_APPEND) == O_APPEND ||
|
||||||
|
(f_info->flags & O_EXCL) == O_EXCL) {
|
||||||
|
return api_error::directory_exists;
|
||||||
|
}
|
||||||
|
|
||||||
return utils::to_api_error(
|
return utils::to_api_error(
|
||||||
remote_instance_->fuse_opendir(api_path.c_str(), f_info->fh));
|
remote_instance_->fuse_opendir(api_path.c_str(), f_info->fh));
|
||||||
@ -378,18 +380,14 @@ auto remote_fuse_drive::read_impl(std::string api_path, char *buffer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if FUSE_USE_VERSION >= 30
|
#if FUSE_USE_VERSION >= 30
|
||||||
auto remote_fuse_drive::readdir_impl(std::string api_path, void *buf,
|
auto remote_fuse_drive::readdir_impl(
|
||||||
fuse_fill_dir_t fuse_fill_dir,
|
std::string api_path, void *buf, fuse_fill_dir_t fuse_fill_dir,
|
||||||
off_t offset,
|
off_t offset, struct fuse_file_info *f_info,
|
||||||
struct fuse_file_info *f_info,
|
fuse_readdir_flags /*flags*/) -> api_error {
|
||||||
fuse_readdir_flags /*flags*/)
|
|
||||||
-> api_error {
|
|
||||||
#else
|
#else
|
||||||
auto remote_fuse_drive::readdir_impl(std::string api_path, void *buf,
|
auto remote_fuse_drive::readdir_impl(
|
||||||
fuse_fill_dir_t fuse_fill_dir,
|
std::string api_path, void *buf, fuse_fill_dir_t fuse_fill_dir,
|
||||||
off_t offset,
|
off_t offset, struct fuse_file_info *f_info) -> api_error {
|
||||||
struct fuse_file_info *f_info)
|
|
||||||
-> api_error {
|
|
||||||
#endif
|
#endif
|
||||||
std::string item_path;
|
std::string item_path;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
@ -417,16 +415,14 @@ auto remote_fuse_drive::readdir_impl(std::string api_path, void *buf,
|
|||||||
return utils::to_api_error(res);
|
return utils::to_api_error(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto remote_fuse_drive::release_impl(std::string api_path,
|
auto remote_fuse_drive::release_impl(
|
||||||
struct fuse_file_info *f_info)
|
std::string api_path, struct fuse_file_info *f_info) -> api_error {
|
||||||
-> api_error {
|
|
||||||
return utils::to_api_error(
|
return utils::to_api_error(
|
||||||
remote_instance_->fuse_release(api_path.c_str(), f_info->fh));
|
remote_instance_->fuse_release(api_path.c_str(), f_info->fh));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto remote_fuse_drive::releasedir_impl(std::string api_path,
|
auto remote_fuse_drive::releasedir_impl(
|
||||||
struct fuse_file_info *f_info)
|
std::string api_path, struct fuse_file_info *f_info) -> api_error {
|
||||||
-> api_error {
|
|
||||||
return utils::to_api_error(
|
return utils::to_api_error(
|
||||||
remote_instance_->fuse_releasedir(api_path.c_str(), f_info->fh));
|
remote_instance_->fuse_releasedir(api_path.c_str(), f_info->fh));
|
||||||
}
|
}
|
||||||
@ -523,8 +519,8 @@ api_error remote_fuse_drive::statfs_x_impl(std::string api_path,
|
|||||||
return utils::to_api_error(res);
|
return utils::to_api_error(res);
|
||||||
}
|
}
|
||||||
#else // __APPLE__
|
#else // __APPLE__
|
||||||
auto remote_fuse_drive::statfs_impl(std::string api_path, struct statvfs *stbuf)
|
auto remote_fuse_drive::statfs_impl(std::string api_path,
|
||||||
-> api_error {
|
struct statvfs *stbuf) -> api_error {
|
||||||
auto res = statvfs(config_.get_data_directory().c_str(), stbuf);
|
auto res = statvfs(config_.get_data_directory().c_str(), stbuf);
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
remote::statfs r_stat{};
|
remote::statfs r_stat{};
|
||||||
@ -551,8 +547,8 @@ auto remote_fuse_drive::truncate_impl(std::string api_path, off_t size,
|
|||||||
struct fuse_file_info * /*f_info*/)
|
struct fuse_file_info * /*f_info*/)
|
||||||
-> api_error {
|
-> api_error {
|
||||||
#else
|
#else
|
||||||
auto remote_fuse_drive::truncate_impl(std::string api_path, off_t size)
|
auto remote_fuse_drive::truncate_impl(std::string api_path,
|
||||||
-> api_error {
|
off_t size) -> api_error {
|
||||||
#endif
|
#endif
|
||||||
return utils::to_api_error(remote_instance_->fuse_truncate(
|
return utils::to_api_error(remote_instance_->fuse_truncate(
|
||||||
api_path.c_str(), static_cast<remote::file_offset>(size)));
|
api_path.c_str(), static_cast<remote::file_offset>(size)));
|
||||||
@ -563,10 +559,9 @@ auto remote_fuse_drive::unlink_impl(std::string api_path) -> api_error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if FUSE_USE_VERSION >= 30
|
#if FUSE_USE_VERSION >= 30
|
||||||
auto remote_fuse_drive::utimens_impl(std::string api_path,
|
auto remote_fuse_drive::utimens_impl(
|
||||||
const struct timespec tv[2],
|
std::string api_path, const struct timespec tv[2],
|
||||||
struct fuse_file_info * /*f_info*/)
|
struct fuse_file_info * /*f_info*/) -> api_error {
|
||||||
-> api_error {
|
|
||||||
#else
|
#else
|
||||||
auto remote_fuse_drive::utimens_impl(std::string api_path,
|
auto remote_fuse_drive::utimens_impl(std::string api_path,
|
||||||
const struct timespec tv[2]) -> api_error {
|
const struct timespec tv[2]) -> api_error {
|
||||||
|
@ -96,7 +96,7 @@ auto remote_server::populate_file_info(const std::string &api_path,
|
|||||||
meta_attributes =
|
meta_attributes =
|
||||||
utils::file::directory(construct_path(api_path)).exists()
|
utils::file::directory(construct_path(api_path)).exists()
|
||||||
? std::to_string(FILE_ATTRIBUTE_DIRECTORY)
|
? std::to_string(FILE_ATTRIBUTE_DIRECTORY)
|
||||||
: std::to_string(FILE_ATTRIBUTE_NORMAL);
|
: std::to_string(FILE_ATTRIBUTE_ARCHIVE);
|
||||||
drive_.set_item_meta(api_path, META_ATTRIBUTES, meta_attributes);
|
drive_.set_item_meta(api_path, META_ATTRIBUTES, meta_attributes);
|
||||||
}
|
}
|
||||||
const auto attributes = utils::string::to_uint32(meta_attributes);
|
const auto attributes = utils::string::to_uint32(meta_attributes);
|
||||||
@ -263,7 +263,12 @@ auto remote_server::fuse_create(const char *path, const remote::file_mode &mode,
|
|||||||
static_cast<int>(remote::create_os_open_flags(flags)), mode);
|
static_cast<int>(remote::create_os_open_flags(flags)), mode);
|
||||||
if (res >= 0) {
|
if (res >= 0) {
|
||||||
handle = static_cast<remote::file_handle>(res);
|
handle = static_cast<remote::file_handle>(res);
|
||||||
set_open_info(res, open_info{0, "", nullptr, file_path});
|
set_open_info(res, open_info{
|
||||||
|
"",
|
||||||
|
nullptr,
|
||||||
|
{},
|
||||||
|
file_path,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ret = ((res < 0) ? -errno : 0);
|
auto ret = ((res < 0) ? -errno : 0);
|
||||||
@ -623,7 +628,12 @@ auto remote_server::fuse_open(const char *path, const remote::open_flags &flags,
|
|||||||
static_cast<int>(remote::create_os_open_flags(flags)));
|
static_cast<int>(remote::create_os_open_flags(flags)));
|
||||||
if (res >= 0) {
|
if (res >= 0) {
|
||||||
handle = static_cast<remote::file_handle>(res);
|
handle = static_cast<remote::file_handle>(res);
|
||||||
set_open_info(res, open_info{0, "", nullptr, file_path});
|
set_open_info(res, open_info{
|
||||||
|
"",
|
||||||
|
nullptr,
|
||||||
|
{},
|
||||||
|
file_path,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
auto ret = ((res < 0) ? -errno : 0);
|
auto ret = ((res < 0) ? -errno : 0);
|
||||||
RAISE_REMOTE_FUSE_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_FUSE_SERVER_EVENT(function_name, file_path, ret);
|
||||||
@ -1020,8 +1030,7 @@ auto remote_server::winfsp_can_delete(PVOID file_desc,
|
|||||||
utils::path::create_api_path(relative_path))
|
utils::path::create_api_path(relative_path))
|
||||||
? STATUS_DIRECTORY_NOT_EMPTY
|
? STATUS_DIRECTORY_NOT_EMPTY
|
||||||
: STATUS_SUCCESS
|
: STATUS_SUCCESS
|
||||||
: drive_.is_processing(utils::path::create_api_path(relative_path))
|
|
||||||
? STATUS_DEVICE_BUSY
|
|
||||||
: STATUS_SUCCESS);
|
: STATUS_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1031,17 +1040,17 @@ auto remote_server::winfsp_can_delete(PVOID file_desc,
|
|||||||
|
|
||||||
auto remote_server::winfsp_cleanup(PVOID /*file_desc*/, PWSTR file_name,
|
auto remote_server::winfsp_cleanup(PVOID /*file_desc*/, PWSTR file_name,
|
||||||
UINT32 flags,
|
UINT32 flags,
|
||||||
BOOLEAN &was_closed) -> packet::error_type {
|
BOOLEAN &was_deleted) -> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto relative_path = utils::string::to_utf8(file_name);
|
const auto relative_path = utils::string::to_utf8(file_name);
|
||||||
const auto file_path = construct_path(relative_path);
|
const auto file_path = construct_path(relative_path);
|
||||||
was_closed = 0;
|
was_deleted = 0U;
|
||||||
|
|
||||||
const auto directory = utils::file::directory(file_path).exists();
|
const auto directory = utils::file::directory(file_path).exists();
|
||||||
if (flags & FileSystemBase::FspCleanupDelete) {
|
if (flags & FileSystemBase::FspCleanupDelete) {
|
||||||
remove_all(file_path);
|
remove_all(file_path);
|
||||||
was_closed = 1;
|
was_deleted = 1U;
|
||||||
|
|
||||||
if (directory) {
|
if (directory) {
|
||||||
rmdir(file_path.c_str());
|
rmdir(file_path.c_str());
|
||||||
@ -1120,14 +1129,11 @@ auto remote_server::winfsp_create(PWSTR file_name, UINT32 create_options,
|
|||||||
attributes |= FILE_ATTRIBUTE_DIRECTORY;
|
attributes |= FILE_ATTRIBUTE_DIRECTORY;
|
||||||
} else {
|
} else {
|
||||||
attributes &= static_cast<UINT32>(~FILE_ATTRIBUTE_DIRECTORY);
|
attributes &= static_cast<UINT32>(~FILE_ATTRIBUTE_DIRECTORY);
|
||||||
|
attributes |= FILE_ATTRIBUTE_ARCHIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not attributes) {
|
remote::file_mode mode{0U};
|
||||||
attributes = FILE_ATTRIBUTE_NORMAL;
|
std::uint32_t flags{0U};
|
||||||
}
|
|
||||||
|
|
||||||
remote::file_mode mode = 0;
|
|
||||||
std::uint32_t flags = 0;
|
|
||||||
utils::windows_create_to_unix(create_options, granted_access, flags, mode);
|
utils::windows_create_to_unix(create_options, granted_access, flags, mode);
|
||||||
|
|
||||||
int res = 0;
|
int res = 0;
|
||||||
@ -1144,7 +1150,12 @@ auto remote_server::winfsp_create(PWSTR file_name, UINT32 create_options,
|
|||||||
*file_desc = reinterpret_cast<PVOID>(res);
|
*file_desc = reinterpret_cast<PVOID>(res);
|
||||||
drive_.set_item_meta(construct_api_path(file_path), META_ATTRIBUTES,
|
drive_.set_item_meta(construct_api_path(file_path), META_ATTRIBUTES,
|
||||||
std::to_string(attributes));
|
std::to_string(attributes));
|
||||||
set_open_info(res, open_info{0, "", nullptr, file_path});
|
set_open_info(res, open_info{
|
||||||
|
"",
|
||||||
|
nullptr,
|
||||||
|
{},
|
||||||
|
file_path,
|
||||||
|
});
|
||||||
|
|
||||||
const auto api_path = utils::path::create_api_path(relative_path);
|
const auto api_path = utils::path::create_api_path(relative_path);
|
||||||
normalized_name = utils::string::replace_copy(api_path, '/', '\\');
|
normalized_name = utils::string::replace_copy(api_path, '/', '\\');
|
||||||
@ -1263,7 +1274,12 @@ auto remote_server::winfsp_open(
|
|||||||
auto res = open(file_path.c_str(), static_cast<int>(flags));
|
auto res = open(file_path.c_str(), static_cast<int>(flags));
|
||||||
if (res >= 0) {
|
if (res >= 0) {
|
||||||
*file_desc = reinterpret_cast<PVOID>(res);
|
*file_desc = reinterpret_cast<PVOID>(res);
|
||||||
set_open_info(res, open_info{0, "", nullptr, file_path});
|
set_open_info(res, open_info{
|
||||||
|
"",
|
||||||
|
nullptr,
|
||||||
|
{},
|
||||||
|
file_path,
|
||||||
|
});
|
||||||
|
|
||||||
const auto api_path = utils::path::create_api_path(relative_path);
|
const auto api_path = utils::path::create_api_path(relative_path);
|
||||||
normalized_name = utils::string::replace_copy(api_path, '/', '\\');
|
normalized_name = utils::string::replace_copy(api_path, '/', '\\');
|
||||||
@ -1315,10 +1331,9 @@ auto remote_server::winfsp_overwrite(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (set_attributes) {
|
if (set_attributes) {
|
||||||
attributes &= static_cast<UINT32>(
|
attributes &= static_cast<UINT32>(~FILE_ATTRIBUTE_NORMAL);
|
||||||
~(FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_NORMAL));
|
|
||||||
if (attributes == 0U) {
|
if (attributes == 0U) {
|
||||||
attributes = FILE_ATTRIBUTE_NORMAL;
|
attributes = FILE_ATTRIBUTE_ARCHIVE;
|
||||||
}
|
}
|
||||||
drive_.set_item_meta(api_path, META_ATTRIBUTES,
|
drive_.set_item_meta(api_path, META_ATTRIBUTES,
|
||||||
std::to_string(attributes));
|
std::to_string(attributes));
|
||||||
@ -1447,15 +1462,15 @@ auto remote_server::winfsp_set_basic_info(
|
|||||||
} else if (attributes == 0) {
|
} else if (attributes == 0) {
|
||||||
attributes = utils::file::directory(file_path).exists()
|
attributes = utils::file::directory(file_path).exists()
|
||||||
? FILE_ATTRIBUTE_DIRECTORY
|
? FILE_ATTRIBUTE_DIRECTORY
|
||||||
: FILE_ATTRIBUTE_NORMAL;
|
: FILE_ATTRIBUTE_ARCHIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto api_path = construct_api_path(file_path);
|
const auto api_path = construct_api_path(file_path);
|
||||||
api_meta_map meta;
|
api_meta_map meta;
|
||||||
if (attributes != 0U) {
|
if (attributes != 0U) {
|
||||||
if (((attributes & FILE_ATTRIBUTE_NORMAL) != 0U) &&
|
attributes &= static_cast<UINT32>(~FILE_ATTRIBUTE_NORMAL);
|
||||||
(attributes != FILE_ATTRIBUTE_NORMAL)) {
|
if (attributes == 0U) {
|
||||||
attributes &= static_cast<UINT32>(~(FILE_ATTRIBUTE_NORMAL));
|
attributes |= static_cast<UINT32>(FILE_ATTRIBUTE_ARCHIVE);
|
||||||
}
|
}
|
||||||
drive_.set_item_meta(api_path, META_ATTRIBUTES,
|
drive_.set_item_meta(api_path, META_ATTRIBUTES,
|
||||||
std::to_string(attributes));
|
std::to_string(attributes));
|
||||||
@ -1677,7 +1692,7 @@ auto remote_server::update_to_windows_format(json &item) -> json & {
|
|||||||
if (item["meta"][META_ATTRIBUTES].empty()) {
|
if (item["meta"][META_ATTRIBUTES].empty()) {
|
||||||
item["meta"][META_ATTRIBUTES] =
|
item["meta"][META_ATTRIBUTES] =
|
||||||
item["directory"].get<bool>() ? std::to_string(FILE_ATTRIBUTE_DIRECTORY)
|
item["directory"].get<bool>() ? std::to_string(FILE_ATTRIBUTE_DIRECTORY)
|
||||||
: std::to_string(FILE_ATTRIBUTE_NORMAL);
|
: std::to_string(FILE_ATTRIBUTE_ARCHIVE);
|
||||||
drive_.set_item_meta(api_path, META_ATTRIBUTES,
|
drive_.set_item_meta(api_path, META_ATTRIBUTES,
|
||||||
item["meta"][META_ATTRIBUTES].get<std::string>());
|
item["meta"][META_ATTRIBUTES].get<std::string>());
|
||||||
}
|
}
|
||||||
|
@ -24,12 +24,13 @@
|
|||||||
#include "events/event_system.hpp"
|
#include "events/event_system.hpp"
|
||||||
#include "events/events.hpp"
|
#include "events/events.hpp"
|
||||||
#include "utils/collection.hpp"
|
#include "utils/collection.hpp"
|
||||||
|
#include "utils/config.hpp"
|
||||||
#include "utils/utils.hpp"
|
#include "utils/utils.hpp"
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
void remote_open_file_table::add_directory(const std::string &client_id,
|
void remote_open_file_table::add_directory(const std::string &client_id,
|
||||||
std::uint64_t handle) {
|
std::uint64_t handle) {
|
||||||
recur_mutex_lock directory_lock(directory_mutex_);
|
recur_mutex_lock lock(file_mutex_);
|
||||||
auto &list = directory_lookup_[client_id];
|
auto &list = directory_lookup_[client_id];
|
||||||
if (utils::collection::excludes(list, handle)) {
|
if (utils::collection::excludes(list, handle)) {
|
||||||
directory_lookup_[client_id].emplace_back(handle);
|
directory_lookup_[client_id].emplace_back(handle);
|
||||||
@ -37,14 +38,32 @@ void remote_open_file_table::add_directory(const std::string &client_id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void remote_open_file_table::close_all(const std::string &client_id) {
|
void remote_open_file_table::close_all(const std::string &client_id) {
|
||||||
std::vector<remote::file_handle> compat_handles;
|
unique_recur_mutex_lock lock(file_mutex_);
|
||||||
unique_recur_mutex_lock compat_lock(compat_mutex_);
|
auto compat_handles =
|
||||||
for (auto &&kv : compat_lookup_) {
|
std::accumulate(compat_file_lookup_.begin(), compat_file_lookup_.end(),
|
||||||
if (kv.second.client_id == client_id) {
|
std::vector<remote::file_handle>(),
|
||||||
compat_handles.emplace_back(kv.first);
|
[&client_id](auto &&list, auto &&value) {
|
||||||
|
auto &&op_info = value.second;
|
||||||
|
if (op_info->client_id == client_id) {
|
||||||
|
list.insert(list.end(), op_info->handles.begin(),
|
||||||
|
op_info->handles.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
});
|
||||||
|
|
||||||
|
auto handles = std::accumulate(
|
||||||
|
file_lookup_.begin(), file_lookup_.end(), std::vector<native_handle>(),
|
||||||
|
[&client_id](auto &&list, auto &&value) {
|
||||||
|
auto &&op_info = value.second;
|
||||||
|
if (op_info->client_id == client_id) {
|
||||||
|
list.insert(list.end(), op_info->handles.begin(),
|
||||||
|
op_info->handles.end());
|
||||||
}
|
}
|
||||||
compat_lock.unlock();
|
|
||||||
|
return list;
|
||||||
|
});
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
for (auto &&handle : compat_handles) {
|
for (auto &&handle : compat_handles) {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
@ -55,32 +74,23 @@ void remote_open_file_table::close_all(const std::string &client_id) {
|
|||||||
remove_compat_open_info(handle);
|
remove_compat_open_info(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<native_handle> handles;
|
|
||||||
unique_recur_mutex_lock file_lock(file_mutex_);
|
|
||||||
for (auto &&kv : file_lookup_) {
|
|
||||||
if (kv.second.client_id == client_id) {
|
|
||||||
handles.emplace_back(kv.first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_lock.unlock();
|
|
||||||
|
|
||||||
for (auto &&handle : handles) {
|
for (auto &&handle : handles) {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
::CloseHandle(handle);
|
::CloseHandle(handle);
|
||||||
#else
|
#else // !defined(_WIN32)
|
||||||
close(handle);
|
close(handle);
|
||||||
#endif
|
#endif // defined(_WIN32)
|
||||||
remove_open_info(handle);
|
remove_open_info(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::uint64_t> dirs;
|
std::vector<std::uint64_t> dirs;
|
||||||
unique_recur_mutex_lock directory_lock(directory_mutex_);
|
lock.lock();
|
||||||
for (auto &&kv : directory_lookup_) {
|
for (auto &&kv : directory_lookup_) {
|
||||||
if (kv.first == client_id) {
|
if (kv.first == client_id) {
|
||||||
dirs.insert(dirs.end(), kv.second.begin(), kv.second.end());
|
dirs.insert(dirs.end(), kv.second.begin(), kv.second.end());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
directory_lock.unlock();
|
lock.unlock();
|
||||||
|
|
||||||
for (auto &&dir : dirs) {
|
for (auto &&dir : dirs) {
|
||||||
remove_directory(client_id, dir);
|
remove_directory(client_id, dir);
|
||||||
@ -90,123 +100,123 @@ void remote_open_file_table::close_all(const std::string &client_id) {
|
|||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
auto remote_open_file_table::get_directory_buffer(const native_handle &handle,
|
auto remote_open_file_table::get_directory_buffer(const native_handle &handle,
|
||||||
PVOID *&buffer) -> bool {
|
PVOID *&buffer) -> bool {
|
||||||
recur_mutex_lock file_lock(file_mutex_);
|
recur_mutex_lock lock(file_mutex_);
|
||||||
if (file_lookup_.find(handle) != file_lookup_.end()) {
|
if (not handle_lookup_.contains(handle)) {
|
||||||
buffer = &file_lookup_[handle].directory_buffer;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = &file_lookup_.at(handle_lookup_.at(handle))->directory_buffer;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif // defined(_WIN32)
|
||||||
|
|
||||||
auto remote_open_file_table::get_open_file_count(
|
auto remote_open_file_table::get_open_file_count(
|
||||||
const std::string &file_path) const -> std::size_t {
|
const std::string &file_path) const -> std::size_t {
|
||||||
unique_recur_mutex_lock file_lock(file_mutex_);
|
recur_mutex_lock lock(file_mutex_);
|
||||||
const auto count = std::accumulate(
|
return (file_lookup_.contains(file_path)
|
||||||
file_lookup_.cbegin(), file_lookup_.cend(), std::size_t(0U),
|
? file_lookup_.at(file_path)->handles.size()
|
||||||
[&file_path](std::size_t total, const auto &kv) -> std::size_t {
|
: 0ULL) +
|
||||||
if (kv.second.path == file_path) {
|
(compat_file_lookup_.contains(file_path)
|
||||||
return ++total;
|
? compat_file_lookup_.at(file_path)->handles.size()
|
||||||
}
|
: 0ULL);
|
||||||
return total;
|
|
||||||
});
|
|
||||||
|
|
||||||
return std::accumulate(
|
|
||||||
compat_lookup_.cbegin(), compat_lookup_.cend(), count,
|
|
||||||
[&file_path](std::size_t total, const auto &kv) -> std::size_t {
|
|
||||||
if (kv.second.path == file_path) {
|
|
||||||
return ++total;
|
|
||||||
}
|
|
||||||
return total;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto remote_open_file_table::get_open_info(const native_handle &handle,
|
auto remote_open_file_table::get_open_info(const native_handle &handle,
|
||||||
open_info &oi) -> bool {
|
open_info &oi) -> bool {
|
||||||
recur_mutex_lock file_lock(file_mutex_);
|
recur_mutex_lock lock(file_mutex_);
|
||||||
if (file_lookup_.find(handle) != file_lookup_.end()) {
|
if (not handle_lookup_.contains(handle)) {
|
||||||
oi = file_lookup_[handle];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
oi = *file_lookup_.at(handle_lookup_.at(handle)).get();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto remote_open_file_table::get_open_file_path(const native_handle &handle)
|
auto remote_open_file_table::get_open_file_path(const native_handle &handle)
|
||||||
-> std::string {
|
-> std::string {
|
||||||
recur_mutex_lock file_lock(file_mutex_);
|
recur_mutex_lock lock(file_mutex_);
|
||||||
if (file_lookup_.find(handle) != file_lookup_.end()) {
|
if (not handle_lookup_.contains(handle)) {
|
||||||
return file_lookup_[handle].path;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
return file_lookup_.at(handle_lookup_.at(handle))->path;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto remote_open_file_table::has_open_directory(const std::string &client_id,
|
auto remote_open_file_table::has_open_directory(const std::string &client_id,
|
||||||
std::uint64_t handle) -> bool {
|
std::uint64_t handle) -> bool {
|
||||||
recur_mutex_lock directory_lock(directory_mutex_);
|
recur_mutex_lock lock(file_mutex_);
|
||||||
auto &list = directory_lookup_[client_id];
|
return (utils::collection::includes(directory_lookup_[client_id], handle));
|
||||||
return (utils::collection::includes(list, handle));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto remote_open_file_table::has_compat_open_info(
|
auto remote_open_file_table::has_compat_open_info(
|
||||||
const remote::file_handle &handle, int error_return) -> int {
|
const remote::file_handle &handle, int error_return) -> int {
|
||||||
recur_mutex_lock compat_lock(compat_mutex_);
|
recur_mutex_lock compat_lock(file_mutex_);
|
||||||
const auto res =
|
auto res = compat_handle_lookup_.contains(handle) ? 0 : -1;
|
||||||
((compat_lookup_.find(handle) == compat_lookup_.end()) ? -1 : 0);
|
|
||||||
if (res == -1) {
|
if (res == -1) {
|
||||||
errno = error_return;
|
errno = error_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void remote_open_file_table::remove_all(const std::string &file_path) {
|
void remote_open_file_table::remove_all(const std::string &file_path) {
|
||||||
unique_recur_mutex_lock file_lock(file_mutex_);
|
unique_recur_mutex_lock lock(file_mutex_);
|
||||||
const auto open_list = std::accumulate(
|
auto compat_open_list = std::accumulate(
|
||||||
file_lookup_.begin(), file_lookup_.end(), std::vector<native_handle>(),
|
compat_file_lookup_.begin(), compat_file_lookup_.end(),
|
||||||
[&file_path](std::vector<native_handle> v,
|
|
||||||
const auto &kv) -> std::vector<native_handle> {
|
|
||||||
if (kv.second.path == file_path) {
|
|
||||||
v.emplace_back(kv.first);
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
});
|
|
||||||
|
|
||||||
const auto compat_open_list = std::accumulate(
|
|
||||||
compat_lookup_.begin(), compat_lookup_.end(),
|
|
||||||
std::vector<remote::file_handle>(),
|
std::vector<remote::file_handle>(),
|
||||||
[&file_path](std::vector<remote::file_handle> v,
|
[&file_path](auto &&list, auto &&kv) -> std::vector<remote::file_handle> {
|
||||||
const auto &kv) -> std::vector<remote::file_handle> {
|
if (kv.first == file_path) {
|
||||||
if (kv.second.path == file_path) {
|
auto *op_info = kv.second.get();
|
||||||
v.emplace_back(kv.first);
|
list.insert(list.end(), op_info->handles.begin(),
|
||||||
|
op_info->handles.end());
|
||||||
}
|
}
|
||||||
return v;
|
return list;
|
||||||
});
|
});
|
||||||
file_lock.unlock();
|
|
||||||
|
|
||||||
for (auto &&handle : open_list) {
|
auto open_list = std::accumulate(
|
||||||
remove_open_info(handle);
|
file_lookup_.begin(), file_lookup_.end(), std::vector<native_handle>(),
|
||||||
|
[&file_path](auto &&list, auto &&kv) -> std::vector<native_handle> {
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
for (auto &&handle : compat_open_list) {
|
for (auto &&handle : compat_open_list) {
|
||||||
remove_compat_open_info(handle);
|
remove_compat_open_info(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto &&handle : open_list) {
|
||||||
|
remove_open_info(handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void remote_open_file_table::remove_compat_open_info(
|
void remote_open_file_table::remove_compat_open_info(
|
||||||
const remote::file_handle &handle) {
|
const remote::file_handle &handle) {
|
||||||
recur_mutex_lock compat_lock(compat_mutex_);
|
recur_mutex_lock compat_lock(file_mutex_);
|
||||||
if (compat_lookup_[handle].count > 0) {
|
if (not compat_handle_lookup_.contains(handle)) {
|
||||||
compat_lookup_[handle].count--;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not compat_lookup_[handle].count) {
|
auto *op_info =
|
||||||
compat_lookup_.erase(handle);
|
compat_file_lookup_.at(compat_handle_lookup_.at(handle)).get();
|
||||||
|
utils::collection::remove_element(op_info->handles, handle);
|
||||||
|
compat_handle_lookup_.erase(handle);
|
||||||
|
|
||||||
|
if (not op_info->handles.empty()) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto path = op_info->path;
|
||||||
|
compat_file_lookup_.erase(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto remote_open_file_table::remove_directory(const std::string &client_id,
|
auto remote_open_file_table::remove_directory(const std::string &client_id,
|
||||||
std::uint64_t handle) -> bool {
|
std::uint64_t handle) -> bool {
|
||||||
recur_mutex_lock directory_lock(directory_mutex_);
|
recur_mutex_lock lock(file_mutex_);
|
||||||
auto &list = directory_lookup_[client_id];
|
auto &list = directory_lookup_[client_id];
|
||||||
if (utils::collection::includes(list, handle)) {
|
if (utils::collection::includes(list, handle)) {
|
||||||
utils::collection::remove_element(list, handle);
|
utils::collection::remove_element(list, handle);
|
||||||
@ -220,48 +230,93 @@ auto remote_open_file_table::remove_directory(const std::string &client_id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void remote_open_file_table::remove_open_info(const native_handle &handle) {
|
void remote_open_file_table::remove_open_info(const native_handle &handle) {
|
||||||
recur_mutex_lock file_lock(file_mutex_);
|
recur_mutex_lock lock(file_mutex_);
|
||||||
if (file_lookup_[handle].count > 0) {
|
if (not handle_lookup_.contains(handle)) {
|
||||||
file_lookup_[handle].count--;
|
return;
|
||||||
}
|
}
|
||||||
if (not file_lookup_[handle].count) {
|
|
||||||
|
auto *op_info = file_lookup_.at(handle_lookup_.at(handle)).get();
|
||||||
|
utils::collection::remove_element(op_info->handles, handle);
|
||||||
|
handle_lookup_.erase(handle);
|
||||||
|
|
||||||
|
if (not op_info->handles.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
if (file_lookup_[handle].directory_buffer) {
|
if (op_info->directory_buffer) {
|
||||||
FspFileSystemDeleteDirectoryBuffer(
|
FspFileSystemDeleteDirectoryBuffer(&op_info->directory_buffer);
|
||||||
&file_lookup_[handle].directory_buffer);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
file_lookup_.erase(handle);
|
|
||||||
|
auto path = op_info->path;
|
||||||
|
file_lookup_.erase(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void remote_open_file_table::remove_and_close_all(const native_handle &handle) {
|
||||||
|
unique_recur_mutex_lock lock(file_mutex_);
|
||||||
|
if (not handle_lookup_.contains(handle)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto op_info = *file_lookup_.at(handle_lookup_.at(handle));
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
|
for (auto &&open_handle : op_info.handles) {
|
||||||
|
#if defined(_WIN32)
|
||||||
|
::CloseHandle(open_handle);
|
||||||
|
#else // !defined(_WIN32)
|
||||||
|
close(open_handle);
|
||||||
|
#endif // defined(_WIN32)
|
||||||
|
remove_open_info(open_handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void remote_open_file_table::set_compat_client_id(
|
void remote_open_file_table::set_compat_client_id(
|
||||||
const remote::file_handle &handle, const std::string &client_id) {
|
const remote::file_handle &handle, const std::string &client_id) {
|
||||||
recur_mutex_lock compat_lock(compat_mutex_);
|
recur_mutex_lock compat_lock(file_mutex_);
|
||||||
compat_lookup_[handle].client_id = client_id;
|
compat_file_lookup_.at(compat_handle_lookup_.at(handle))->client_id =
|
||||||
|
client_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void remote_open_file_table::set_client_id(const native_handle &handle,
|
void remote_open_file_table::set_client_id(const native_handle &handle,
|
||||||
const std::string &client_id) {
|
const std::string &client_id) {
|
||||||
recur_mutex_lock file_lock(file_mutex_);
|
recur_mutex_lock lock(file_mutex_);
|
||||||
file_lookup_[handle].client_id = client_id;
|
file_lookup_.at(handle_lookup_.at(handle))->client_id = client_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void remote_open_file_table::set_compat_open_info(
|
void remote_open_file_table::set_compat_open_info(
|
||||||
const remote::file_handle &handle, const std::string &file_path) {
|
const remote::file_handle &handle, const std::string &file_path) {
|
||||||
recur_mutex_lock compat_lock(compat_mutex_);
|
recur_mutex_lock compat_lock(file_mutex_);
|
||||||
if (compat_lookup_.find(handle) == compat_lookup_.end()) {
|
if (compat_handle_lookup_.contains(handle)) {
|
||||||
compat_lookup_[handle] = {0, "", file_path};
|
return;
|
||||||
}
|
}
|
||||||
compat_lookup_[handle].count++;
|
|
||||||
|
if (not compat_file_lookup_.contains(file_path)) {
|
||||||
|
compat_file_lookup_[file_path] =
|
||||||
|
std::make_unique<compat_open_info>(compat_open_info{
|
||||||
|
"",
|
||||||
|
{},
|
||||||
|
file_path,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
compat_handle_lookup_[handle] = file_path;
|
||||||
|
compat_file_lookup_.at(file_path)->handles.emplace_back(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void remote_open_file_table::set_open_info(const native_handle &handle,
|
void remote_open_file_table::set_open_info(const native_handle &handle,
|
||||||
open_info oi) {
|
open_info op_info) {
|
||||||
recur_mutex_lock file_lock(file_mutex_);
|
recur_mutex_lock lock(file_mutex_);
|
||||||
if (file_lookup_.find(handle) == file_lookup_.end()) {
|
if (handle_lookup_.contains(handle)) {
|
||||||
file_lookup_[handle] = std::move(oi);
|
return;
|
||||||
}
|
}
|
||||||
file_lookup_[handle].count++;
|
|
||||||
|
if (not file_lookup_.contains(op_info.path)) {
|
||||||
|
file_lookup_[op_info.path] = std::make_unique<open_info>(op_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_lookup_[handle] = op_info.path;
|
||||||
|
file_lookup_.at(op_info.path)->handles.emplace_back(handle);
|
||||||
}
|
}
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
@ -47,12 +47,7 @@ E_SIMPLE3(remote_winfsp_client_event, debug, true,
|
|||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
remote_client::remote_client(const app_config &config)
|
remote_client::remote_client(const app_config &config)
|
||||||
: config_(config),
|
: config_(config), packet_client_(config.get_remote_config()) {}
|
||||||
packet_client_(
|
|
||||||
config.get_remote_host_name_or_ip(),
|
|
||||||
config.get_remote_max_connections(), config.get_remote_port(),
|
|
||||||
config.get_remote_receive_timeout_secs(),
|
|
||||||
config.get_remote_send_timeout_secs(), config.get_remote_token()) {}
|
|
||||||
|
|
||||||
auto remote_client::winfsp_can_delete(PVOID file_desc, PWSTR file_name)
|
auto remote_client::winfsp_can_delete(PVOID file_desc, PWSTR file_name)
|
||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
@ -136,7 +131,7 @@ auto remote_client::json_release_directory_snapshot(
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto remote_client::winfsp_cleanup(PVOID file_desc, PWSTR file_name,
|
auto remote_client::winfsp_cleanup(PVOID file_desc, PWSTR file_name,
|
||||||
UINT32 flags, BOOLEAN &was_closed)
|
UINT32 flags, BOOLEAN &was_deleted)
|
||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
@ -148,7 +143,7 @@ auto remote_client::winfsp_cleanup(PVOID file_desc, PWSTR file_name,
|
|||||||
get_open_file_path(handle),
|
get_open_file_path(handle),
|
||||||
};
|
};
|
||||||
|
|
||||||
was_closed = 0;
|
was_deleted = 0U;
|
||||||
|
|
||||||
packet request;
|
packet request;
|
||||||
request.encode(file_desc);
|
request.encode(file_desc);
|
||||||
@ -160,10 +155,12 @@ auto remote_client::winfsp_cleanup(PVOID file_desc, PWSTR file_name,
|
|||||||
auto ret{
|
auto ret{
|
||||||
packet_client_.send(function_name, request, response, service_flags),
|
packet_client_.send(function_name, request, response, service_flags),
|
||||||
};
|
};
|
||||||
DECODE_OR_IGNORE(&response, was_closed);
|
|
||||||
if (was_closed != 0U) {
|
DECODE_OR_IGNORE(&response, was_deleted);
|
||||||
|
if (was_deleted != 0U) {
|
||||||
remove_all(file_path);
|
remove_all(file_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -222,11 +219,16 @@ auto remote_client::winfsp_create(PWSTR file_name, UINT32 create_options,
|
|||||||
DECODE_OR_IGNORE(&response, *file_info);
|
DECODE_OR_IGNORE(&response, *file_info);
|
||||||
DECODE_OR_IGNORE(&response, normalized_name);
|
DECODE_OR_IGNORE(&response, normalized_name);
|
||||||
DECODE_OR_IGNORE(&response, exists);
|
DECODE_OR_IGNORE(&response, exists);
|
||||||
|
|
||||||
if (ret == STATUS_SUCCESS) {
|
if (ret == STATUS_SUCCESS) {
|
||||||
*file_desc = reinterpret_cast<PVOID>(handle);
|
*file_desc = reinterpret_cast<PVOID>(handle);
|
||||||
set_open_info(
|
set_open_info(to_handle(*file_desc),
|
||||||
to_handle(*file_desc),
|
open_info{
|
||||||
open_info{0, "", nullptr, utils::string::to_utf8(file_name)});
|
"",
|
||||||
|
nullptr,
|
||||||
|
{},
|
||||||
|
utils::string::to_utf8(file_name),
|
||||||
|
});
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
if (exists) {
|
if (exists) {
|
||||||
::SetLastError(ERROR_ALREADY_EXISTS);
|
::SetLastError(ERROR_ALREADY_EXISTS);
|
||||||
@ -390,9 +392,13 @@ auto remote_client::winfsp_open(PWSTR file_name, UINT32 create_options,
|
|||||||
|
|
||||||
if (ret == STATUS_SUCCESS) {
|
if (ret == STATUS_SUCCESS) {
|
||||||
*file_desc = reinterpret_cast<PVOID>(handle);
|
*file_desc = reinterpret_cast<PVOID>(handle);
|
||||||
set_open_info(
|
set_open_info(to_handle(*file_desc),
|
||||||
to_handle(*file_desc),
|
open_info{
|
||||||
open_info{0, "", nullptr, utils::string::to_utf8(file_name)});
|
"",
|
||||||
|
nullptr,
|
||||||
|
{},
|
||||||
|
utils::string::to_utf8(file_name),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,8 +133,8 @@ auto remote_server::fuse_chflags(const char *path, std::uint32_t /*flags*/)
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
const auto ret = STATUS_NOT_IMPLEMENTED;
|
auto ret = STATUS_NOT_IMPLEMENTED;
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -144,8 +144,8 @@ auto remote_server::fuse_chmod(const char *path,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
const auto ret = STATUS_NOT_IMPLEMENTED;
|
auto ret = STATUS_NOT_IMPLEMENTED;
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -156,8 +156,8 @@ auto remote_server::fuse_chown(const char *path,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
const auto ret = STATUS_NOT_IMPLEMENTED;
|
auto ret = STATUS_NOT_IMPLEMENTED;
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -171,12 +171,12 @@ auto remote_server::fuse_destroy() -> packet::error_type {
|
|||||||
|
|
||||||
/*packet::error_type remote_server::fuse_fallocate(const char *path, const
|
/*packet::error_type remote_server::fuse_fallocate(const char *path, const
|
||||||
std::int32_t &mode, const remote::file_offset &offset, const remote::file_offset
|
std::int32_t &mode, const remote::file_offset &offset, const remote::file_offset
|
||||||
&length, const remote::file_handle &handle) { const auto file_path =
|
&length, const remote::file_handle &handle) { auto file_path =
|
||||||
construct_path(path); auto res = HasOpenFileCompatInfo(handle, EBADF); if (res
|
construct_path(path); auto res = HasOpenFileCompatInfo(handle, EBADF); if (res
|
||||||
== 0) { res = _chsize_s(static_cast<int>(handle), offset + length);
|
== 0) { res = _chsize_s(static_cast<int>(handle), offset + length);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ret = ((res < 0) ? -errno : 0);
|
auto ret = ((res < 0) ? -errno : 0);
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}*/
|
}*/
|
||||||
@ -189,7 +189,7 @@ auto remote_server::fuse_fgetattr(const char *path, remote::stat &r_stat,
|
|||||||
|
|
||||||
r_stat = {};
|
r_stat = {};
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
|
|
||||||
auto res{
|
auto res{
|
||||||
has_compat_open_info(handle, EBADF),
|
has_compat_open_info(handle, EBADF),
|
||||||
@ -203,7 +203,7 @@ auto remote_server::fuse_fgetattr(const char *path, remote::stat &r_stat,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ret = ((res < 0) ? -errno : 0);
|
auto ret = ((res < 0) ? -errno : 0);
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -214,8 +214,8 @@ auto remote_server::fuse_fsetattr_x(const char *path,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
const auto ret = STATUS_NOT_IMPLEMENTED;
|
auto ret = STATUS_NOT_IMPLEMENTED;
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -226,7 +226,7 @@ auto remote_server::fuse_fsync(const char *path,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
|
|
||||||
auto res{
|
auto res{
|
||||||
has_compat_open_info(handle, EBADF),
|
has_compat_open_info(handle, EBADF),
|
||||||
@ -245,7 +245,7 @@ auto remote_server::fuse_fsync(const char *path,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ret = ((res < 0) ? -errno : 0);
|
auto ret = ((res < 0) ? -errno : 0);
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -256,7 +256,7 @@ auto remote_server::fuse_ftruncate(const char *path,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
|
|
||||||
auto res{
|
auto res{
|
||||||
has_compat_open_info(handle, EBADF),
|
has_compat_open_info(handle, EBADF),
|
||||||
@ -278,7 +278,7 @@ auto remote_server::fuse_ftruncate(const char *path,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ret = ((res < 0) ? -errno : 0);
|
auto ret = ((res < 0) ? -errno : 0);
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -289,7 +289,7 @@ auto remote_server::fuse_getattr(const char *path, remote::stat &r_st,
|
|||||||
|
|
||||||
r_st = {};
|
r_st = {};
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
|
|
||||||
directory = utils::file::directory(file_path).exists();
|
directory = utils::file::directory(file_path).exists();
|
||||||
|
|
||||||
@ -301,20 +301,20 @@ auto remote_server::fuse_getattr(const char *path, remote::stat &r_st,
|
|||||||
populate_stat(path, directory, r_st, st1);
|
populate_stat(path, directory, r_st, st1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ret = ((res < 0) ? -errno : 0);
|
auto ret = ((res < 0) ? -errno : 0);
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*packet::error_type remote_server::fuse_getxattr(const char *path, const char
|
/*packet::error_type remote_server::fuse_getxattr(const char *path, const char
|
||||||
*name, char *value, const remote::file_size &size) { const auto file_path =
|
*name, char *value, const remote::file_size &size) { auto file_path =
|
||||||
construct_path(path); const auto ret = STATUS_NOT_IMPLEMENTED;
|
construct_path(path); auto ret = STATUS_NOT_IMPLEMENTED;
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret); return ret;
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret); return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
packet::error_type remote_server::fuse_getxattr_osx(const char *path, const char
|
packet::error_type remote_server::fuse_getxattr_osx(const char *path, const char
|
||||||
*name, char *value, const remote::file_size &size, std::uint32_t position) {
|
*name, char *value, const remote::file_size &size, std::uint32_t position) {
|
||||||
const auto file_path = construct_path(path); const auto ret =
|
auto file_path = construct_path(path); auto ret =
|
||||||
STATUS_NOT_IMPLEMENTED; RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name,
|
STATUS_NOT_IMPLEMENTED; RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name,
|
||||||
file_path, ret); return ret;
|
file_path, ret); return ret;
|
||||||
}*/
|
}*/
|
||||||
@ -325,8 +325,8 @@ auto remote_server::fuse_getxtimes(const char *path,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
const auto ret = STATUS_NOT_IMPLEMENTED;
|
auto ret = STATUS_NOT_IMPLEMENTED;
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -339,8 +339,8 @@ auto remote_server::fuse_init() -> packet::error_type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*packet::error_type remote_server::fuse_listxattr(const char *path, char
|
/*packet::error_type remote_server::fuse_listxattr(const char *path, char
|
||||||
*buffer, const remote::file_size &size) { const auto file_path =
|
*buffer, const remote::file_size &size) { auto file_path =
|
||||||
construct_path(path); const auto ret = STATUS_NOT_IMPLEMENTED;
|
construct_path(path); auto ret = STATUS_NOT_IMPLEMENTED;
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}*/
|
}*/
|
||||||
@ -350,11 +350,11 @@ auto remote_server::fuse_mkdir(const char *path,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
auto res{
|
auto res{
|
||||||
_mkdir(file_path.c_str()),
|
_mkdir(file_path.c_str()),
|
||||||
};
|
};
|
||||||
const auto ret = ((res < 0) ? -errno : 0);
|
auto ret = ((res < 0) ? -errno : 0);
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -363,8 +363,8 @@ auto remote_server::fuse_opendir(const char *path, remote::file_handle &handle)
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
const auto unicode_file_path = utils::string::from_utf8(file_path);
|
auto unicode_file_path = utils::string::from_utf8(file_path);
|
||||||
auto res{-1};
|
auto res{-1};
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
|
|
||||||
@ -379,7 +379,7 @@ auto remote_server::fuse_opendir(const char *path, remote::file_handle &handle)
|
|||||||
errno = 0;
|
errno = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ret = ((res < 0) ? -errno : 0);
|
auto ret = ((res < 0) ? -errno : 0);
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -392,13 +392,13 @@ auto remote_server::fuse_create(const char *path, const remote::file_mode &mode,
|
|||||||
|
|
||||||
auto ret = -1;
|
auto ret = -1;
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
const auto directory_op = ((flags & remote::open_flags::directory) ==
|
auto directory_op = ((flags & remote::open_flags::directory) ==
|
||||||
remote::open_flags::directory);
|
remote::open_flags::directory);
|
||||||
std::int32_t perms = 0;
|
std::int32_t perms = 0;
|
||||||
const auto open_flags =
|
auto open_flags =
|
||||||
utils::unix_open_flags_to_flags_and_perms(mode, flags, perms);
|
utils::unix_open_flags_to_flags_and_perms(mode, flags, perms);
|
||||||
const auto create_op = (open_flags & _O_CREAT);
|
auto create_op = (open_flags & _O_CREAT);
|
||||||
|
|
||||||
if ((create_op != 0) && directory_op) {
|
if ((create_op != 0) && directory_op) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
@ -427,7 +427,7 @@ auto remote_server::fuse_open(const char *path, const remote::open_flags &flags,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
auto res{-1};
|
auto res{-1};
|
||||||
|
|
||||||
if ((flags & remote::open_flags::directory) ==
|
if ((flags & remote::open_flags::directory) ==
|
||||||
@ -435,7 +435,7 @@ auto remote_server::fuse_open(const char *path, const remote::open_flags &flags,
|
|||||||
errno = EACCES;
|
errno = EACCES;
|
||||||
} else {
|
} else {
|
||||||
std::int32_t perms = 0;
|
std::int32_t perms = 0;
|
||||||
const auto open_flags =
|
auto open_flags =
|
||||||
utils::unix_open_flags_to_flags_and_perms(0, flags, perms) &
|
utils::unix_open_flags_to_flags_and_perms(0, flags, perms) &
|
||||||
(~_O_CREAT);
|
(~_O_CREAT);
|
||||||
int file = -1;
|
int file = -1;
|
||||||
@ -448,7 +448,7 @@ auto remote_server::fuse_open(const char *path, const remote::open_flags &flags,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ret = ((res < 0) ? -errno : 0);
|
auto ret = ((res < 0) ? -errno : 0);
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -460,7 +460,7 @@ auto remote_server::fuse_read(const char *path, char *buffer,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
auto &data = *reinterpret_cast<data_buffer *>(buffer);
|
auto &data = *reinterpret_cast<data_buffer *>(buffer);
|
||||||
auto res{0};
|
auto res{0};
|
||||||
if (read_size > std::numeric_limits<std::size_t>::max()) {
|
if (read_size > std::numeric_limits<std::size_t>::max()) {
|
||||||
@ -481,7 +481,7 @@ auto remote_server::fuse_read(const char *path, char *buffer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ret = ((res < 0) ? -errno : static_cast<int>(data.size()));
|
auto ret = ((res < 0) ? -errno : static_cast<int>(data.size()));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
}
|
}
|
||||||
@ -492,13 +492,13 @@ auto remote_server::fuse_rename(const char *from, const char *to)
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto from_path = utils::path::combine(mount_location_, {from});
|
auto from_path = utils::path::combine(mount_location_, {from});
|
||||||
const auto to_path = utils::path::combine(mount_location_, {to});
|
auto to_path = utils::path::combine(mount_location_, {to});
|
||||||
auto res{
|
auto res{
|
||||||
rename(from_path.c_str(), to_path.c_str()),
|
rename(from_path.c_str(), to_path.c_str()),
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto ret = ((res < 0) ? -errno : 0);
|
auto ret = ((res < 0) ? -errno : 0);
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, from + std::string("|") + to,
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, from + std::string("|") + to,
|
||||||
ret);
|
ret);
|
||||||
return ret;
|
return ret;
|
||||||
@ -511,7 +511,7 @@ auto remote_server::fuse_write(const char *path, const char *buffer,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
std::size_t bytes_written{};
|
std::size_t bytes_written{};
|
||||||
auto res{0};
|
auto res{0};
|
||||||
if (write_size > std::numeric_limits<std::size_t>::max()) {
|
if (write_size > std::numeric_limits<std::size_t>::max()) {
|
||||||
@ -533,7 +533,7 @@ auto remote_server::fuse_write(const char *path, const char *buffer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ret = ((res < 0) ? -errno : static_cast<int>(bytes_written));
|
auto ret = ((res < 0) ? -errno : static_cast<int>(bytes_written));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
}
|
}
|
||||||
@ -555,7 +555,7 @@ auto remote_server::fuse_readdir(const char *path,
|
|||||||
std::string &item_path) -> packet::error_type {
|
std::string &item_path) -> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
auto res{0};
|
auto res{0};
|
||||||
if (offset > std::numeric_limits<std::size_t>::max()) {
|
if (offset > std::numeric_limits<std::size_t>::max()) {
|
||||||
errno = ERANGE;
|
errno = ERANGE;
|
||||||
@ -570,7 +570,7 @@ auto remote_server::fuse_readdir(const char *path,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ret = ((res < 0) ? -errno : 0);
|
auto ret = ((res < 0) ? -errno : 0);
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -580,14 +580,14 @@ auto remote_server::fuse_release(const char *path,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
|
|
||||||
remove_compat_open_info(handle);
|
remove_compat_open_info(handle);
|
||||||
auto res{
|
auto res{
|
||||||
_close(static_cast<int>(handle)),
|
_close(static_cast<int>(handle)),
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto ret = ((res < 0) ? -errno : 0);
|
auto ret = ((res < 0) ? -errno : 0);
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -597,14 +597,14 @@ auto remote_server::fuse_releasedir(const char *path,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, 0);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*packet::error_type remote_server::fuse_removexattr(const char *path, const
|
/*packet::error_type remote_server::fuse_removexattr(const char *path, const
|
||||||
char *name) { const auto file_path = construct_path(path); const auto ret =
|
char *name) { auto file_path = construct_path(path); auto ret =
|
||||||
STATUS_NOT_IMPLEMENTED; RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name,
|
STATUS_NOT_IMPLEMENTED; RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name,
|
||||||
file_path, ret); return ret;
|
file_path, ret); return ret;
|
||||||
}*/
|
}*/
|
||||||
@ -612,11 +612,11 @@ file_path, ret); return ret;
|
|||||||
auto remote_server::fuse_rmdir(const char *path) -> packet::error_type {
|
auto remote_server::fuse_rmdir(const char *path) -> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
auto res{
|
auto res{
|
||||||
_rmdir(file_path.c_str()),
|
_rmdir(file_path.c_str()),
|
||||||
};
|
};
|
||||||
const auto ret = ((res < 0) ? -errno : 0);
|
auto ret = ((res < 0) ? -errno : 0);
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -626,8 +626,8 @@ auto remote_server::fuse_setattr_x(const char *path,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
const auto ret = STATUS_NOT_IMPLEMENTED;
|
auto ret = STATUS_NOT_IMPLEMENTED;
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -637,8 +637,8 @@ auto remote_server::fuse_setbkuptime(const char *path,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
const auto ret = STATUS_NOT_IMPLEMENTED;
|
auto ret = STATUS_NOT_IMPLEMENTED;
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -648,8 +648,8 @@ auto remote_server::fuse_setchgtime(const char *path,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
const auto ret = STATUS_NOT_IMPLEMENTED;
|
auto ret = STATUS_NOT_IMPLEMENTED;
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -659,8 +659,8 @@ auto remote_server::fuse_setcrtime(const char *path,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
const auto ret = STATUS_NOT_IMPLEMENTED;
|
auto ret = STATUS_NOT_IMPLEMENTED;
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -674,15 +674,15 @@ auto remote_server::fuse_setvolname(const char *volname) -> packet::error_type {
|
|||||||
|
|
||||||
/*packet::error_type remote_server::fuse_setxattr(const char *path, const char
|
/*packet::error_type remote_server::fuse_setxattr(const char *path, const char
|
||||||
*name, const char *value, const remote::file_size &size, const std::int32_t
|
*name, const char *value, const remote::file_size &size, const std::int32_t
|
||||||
&flags) { const auto file_path = construct_path(path); const auto ret =
|
&flags) { auto file_path = construct_path(path); auto ret =
|
||||||
STATUS_NOT_IMPLEMENTED; RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name,
|
STATUS_NOT_IMPLEMENTED; RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name,
|
||||||
file_path, ret); return ret;
|
file_path, ret); return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
packet::error_type remote_server::fuse_setxattr_osx(const char *path, const char
|
packet::error_type remote_server::fuse_setxattr_osx(const char *path, const char
|
||||||
*name, const char *value, const remote::file_size &size, const std::int32_t
|
*name, const char *value, const remote::file_size &size, const std::int32_t
|
||||||
&flags, const std::uint32_t &position) { const auto file_path =
|
&flags, const std::uint32_t &position) { auto file_path =
|
||||||
construct_path(path); const auto ret = STATUS_NOT_IMPLEMENTED;
|
construct_path(path); auto ret = STATUS_NOT_IMPLEMENTED;
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}*/
|
}*/
|
||||||
@ -691,11 +691,11 @@ auto remote_server::fuse_statfs(const char *path, std::uint64_t frsize,
|
|||||||
remote::statfs &r_stat) -> packet::error_type {
|
remote::statfs &r_stat) -> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
|
|
||||||
const auto total_bytes = drive_.get_total_drive_space();
|
auto total_bytes = drive_.get_total_drive_space();
|
||||||
const auto total_used = drive_.get_used_drive_space();
|
auto total_used = drive_.get_used_drive_space();
|
||||||
const auto used_blocks = utils::divide_with_ceiling(
|
auto used_blocks = utils::divide_with_ceiling(
|
||||||
total_used, static_cast<std::uint64_t>(frsize));
|
total_used, static_cast<std::uint64_t>(frsize));
|
||||||
r_stat.f_files = 4294967295;
|
r_stat.f_files = 4294967295;
|
||||||
r_stat.f_blocks = utils::divide_with_ceiling(
|
r_stat.f_blocks = utils::divide_with_ceiling(
|
||||||
@ -714,11 +714,11 @@ auto remote_server::fuse_statfs_x(const char *path, std::uint64_t bsize,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
|
|
||||||
const auto total_bytes = drive_.get_total_drive_space();
|
auto total_bytes = drive_.get_total_drive_space();
|
||||||
const auto total_used = drive_.get_used_drive_space();
|
auto total_used = drive_.get_used_drive_space();
|
||||||
const auto used_blocks =
|
auto used_blocks =
|
||||||
utils::divide_with_ceiling(total_used, static_cast<std::uint64_t>(bsize));
|
utils::divide_with_ceiling(total_used, static_cast<std::uint64_t>(bsize));
|
||||||
r_stat.f_blocks = utils::divide_with_ceiling(
|
r_stat.f_blocks = utils::divide_with_ceiling(
|
||||||
total_bytes, static_cast<std::uint64_t>(bsize));
|
total_bytes, static_cast<std::uint64_t>(bsize));
|
||||||
@ -740,12 +740,12 @@ auto remote_server::fuse_truncate(const char *path,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
const auto unicode_file_path = utils::string::from_utf8(file_path);
|
auto unicode_file_path = utils::string::from_utf8(file_path);
|
||||||
auto res{-1};
|
auto res{-1};
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
|
|
||||||
const auto flags_and_attributes =
|
auto flags_and_attributes =
|
||||||
FILE_FLAG_BACKUP_SEMANTICS |
|
FILE_FLAG_BACKUP_SEMANTICS |
|
||||||
(::PathIsDirectoryW(unicode_file_path.c_str()) != 0
|
(::PathIsDirectoryW(unicode_file_path.c_str()) != 0
|
||||||
? FILE_ATTRIBUTE_DIRECTORY | FILE_FLAG_POSIX_SEMANTICS
|
? FILE_ATTRIBUTE_DIRECTORY | FILE_FLAG_POSIX_SEMANTICS
|
||||||
@ -766,7 +766,7 @@ auto remote_server::fuse_truncate(const char *path,
|
|||||||
::CloseHandle(os_handle);
|
::CloseHandle(os_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ret = ((res < 0) ? -errno : 0);
|
auto ret = ((res < 0) ? -errno : 0);
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -774,11 +774,11 @@ auto remote_server::fuse_truncate(const char *path,
|
|||||||
auto remote_server::fuse_unlink(const char *path) -> packet::error_type {
|
auto remote_server::fuse_unlink(const char *path) -> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
auto res{
|
auto res{
|
||||||
_unlink(file_path.c_str()),
|
_unlink(file_path.c_str()),
|
||||||
};
|
};
|
||||||
const auto ret = ((res < 0) ? -errno : 0);
|
auto ret = ((res < 0) ? -errno : 0);
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -788,13 +788,13 @@ auto remote_server::fuse_utimens(const char *path, const remote::file_time *tv,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
const auto unicode_file_path = utils::string::from_utf8(file_path);
|
auto unicode_file_path = utils::string::from_utf8(file_path);
|
||||||
|
|
||||||
auto res{-1};
|
auto res{-1};
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
|
|
||||||
const auto flags_and_attributes =
|
auto flags_and_attributes =
|
||||||
FILE_FLAG_BACKUP_SEMANTICS |
|
FILE_FLAG_BACKUP_SEMANTICS |
|
||||||
(::PathIsDirectoryW(unicode_file_path.c_str()) != 0
|
(::PathIsDirectoryW(unicode_file_path.c_str()) != 0
|
||||||
? FILE_ATTRIBUTE_DIRECTORY | FILE_FLAG_POSIX_SEMANTICS
|
? FILE_ATTRIBUTE_DIRECTORY | FILE_FLAG_POSIX_SEMANTICS
|
||||||
@ -838,7 +838,7 @@ auto remote_server::fuse_utimens(const char *path, const remote::file_time *tv,
|
|||||||
::CloseHandle(os_handle);
|
::CloseHandle(os_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ret = ((res < 0) ? -errno : 0);
|
auto ret = ((res < 0) ? -errno : 0);
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -849,7 +849,7 @@ auto remote_server::json_create_directory_snapshot(const std::string &path,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
|
|
||||||
auto res{-1};
|
auto res{-1};
|
||||||
errno = ENOENT;
|
errno = ENOENT;
|
||||||
@ -868,7 +868,7 @@ auto remote_server::json_create_directory_snapshot(const std::string &path,
|
|||||||
errno = 0;
|
errno = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ret = ((res < 0) ? -errno : 0);
|
auto ret = ((res < 0) ? -errno : 0);
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -878,7 +878,7 @@ auto remote_server::json_read_directory_snapshot(
|
|||||||
std::uint32_t page, json &json_data) -> packet::error_type {
|
std::uint32_t page, json &json_data) -> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
|
|
||||||
int res{-EBADF};
|
int res{-EBADF};
|
||||||
auto iter = directory_cache_.get_directory(handle);
|
auto iter = directory_cache_.get_directory(handle);
|
||||||
@ -898,7 +898,7 @@ auto remote_server::json_read_directory_snapshot(
|
|||||||
iter->get_count(), REPERTORY_DIRECTORY_PAGE_SIZE);
|
iter->get_count(), REPERTORY_DIRECTORY_PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ret = ((res < 0) ? -errno : 0);
|
auto ret = ((res < 0) ? -errno : 0);
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -908,7 +908,7 @@ auto remote_server::json_release_directory_snapshot(
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = construct_path(path);
|
auto file_path = construct_path(path);
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, 0);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -923,7 +923,7 @@ auto remote_server::winfsp_can_delete(PVOID file_desc, PWSTR /*file_name*/)
|
|||||||
|
|
||||||
auto ret = has_open_info(handle, STATUS_INVALID_HANDLE);
|
auto ret = has_open_info(handle, STATUS_INVALID_HANDLE);
|
||||||
if (ret == STATUS_SUCCESS) {
|
if (ret == STATUS_SUCCESS) {
|
||||||
FILE_DISPOSITION_INFO dispositionInfo = {TRUE};
|
FILE_DISPOSITION_INFO dispositionInfo{TRUE};
|
||||||
ret = ::SetFileInformationByHandle(handle, FileDispositionInfo,
|
ret = ::SetFileInformationByHandle(handle, FileDispositionInfo,
|
||||||
&dispositionInfo,
|
&dispositionInfo,
|
||||||
sizeof(FILE_DISPOSITION_INFO)) != 0
|
sizeof(FILE_DISPOSITION_INFO)) != 0
|
||||||
@ -936,21 +936,21 @@ auto remote_server::winfsp_can_delete(PVOID file_desc, PWSTR /*file_name*/)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto remote_server::winfsp_cleanup(PVOID file_desc, PWSTR /*file_name*/,
|
auto remote_server::winfsp_cleanup(PVOID file_desc, PWSTR /*file_name*/,
|
||||||
UINT32 flags, BOOLEAN &was_closed)
|
UINT32 flags, BOOLEAN &was_deleted)
|
||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = get_open_file_path(file_desc);
|
auto file_path = get_open_file_path(file_desc);
|
||||||
was_closed = FALSE;
|
was_deleted = FALSE;
|
||||||
auto *handle = reinterpret_cast<HANDLE>(file_desc);
|
auto *handle = reinterpret_cast<HANDLE>(file_desc);
|
||||||
const auto ret = has_open_info(handle, STATUS_INVALID_HANDLE);
|
auto ret = has_open_info(handle, STATUS_INVALID_HANDLE);
|
||||||
if (ret == STATUS_SUCCESS) {
|
if (ret == STATUS_SUCCESS) {
|
||||||
if ((flags & FileSystemBase::CleanupDelete) != 0U) {
|
if ((flags & FspCleanupDelete) != 0U) {
|
||||||
::CloseHandle(handle);
|
remove_and_close_all(file_desc);
|
||||||
remove_open_info(file_desc);
|
was_deleted = TRUE;
|
||||||
was_closed = TRUE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -958,7 +958,7 @@ auto remote_server::winfsp_cleanup(PVOID file_desc, PWSTR /*file_name*/,
|
|||||||
auto remote_server::winfsp_close(PVOID file_desc) -> packet::error_type {
|
auto remote_server::winfsp_close(PVOID file_desc) -> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = get_open_file_path(file_desc);
|
auto file_path = get_open_file_path(file_desc);
|
||||||
|
|
||||||
auto *handle = reinterpret_cast<HANDLE>(file_desc);
|
auto *handle = reinterpret_cast<HANDLE>(file_desc);
|
||||||
if (has_open_info(handle, STATUS_INVALID_HANDLE) == STATUS_SUCCESS) {
|
if (has_open_info(handle, STATUS_INVALID_HANDLE) == STATUS_SUCCESS) {
|
||||||
@ -978,7 +978,7 @@ auto remote_server::winfsp_create(PWSTR file_name, UINT32 create_options,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = utils::string::from_utf8(utils::path::combine(
|
auto file_path = utils::string::from_utf8(utils::path::combine(
|
||||||
mount_location_, {utils::string::to_utf8(file_name)}));
|
mount_location_, {utils::string::to_utf8(file_name)}));
|
||||||
exists = static_cast<BOOLEAN>(
|
exists = static_cast<BOOLEAN>(
|
||||||
utils::file::file(
|
utils::file::file(
|
||||||
@ -986,30 +986,34 @@ auto remote_server::winfsp_create(PWSTR file_name, UINT32 create_options,
|
|||||||
{utils::string::to_utf8(file_name)}))
|
{utils::string::to_utf8(file_name)}))
|
||||||
.exists());
|
.exists());
|
||||||
|
|
||||||
auto create_flags = FILE_FLAG_BACKUP_SEMANTICS;
|
attributes |= FILE_FLAG_BACKUP_SEMANTICS;
|
||||||
if ((create_options & FILE_DIRECTORY_FILE) != 0U) {
|
if ((create_options & FILE_DIRECTORY_FILE) != 0U) {
|
||||||
create_flags |= FILE_FLAG_POSIX_SEMANTICS;
|
attributes |= FILE_FLAG_POSIX_SEMANTICS;
|
||||||
attributes |= FILE_ATTRIBUTE_DIRECTORY;
|
|
||||||
} else {
|
|
||||||
attributes &= static_cast<UINT32>(~FILE_ATTRIBUTE_DIRECTORY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attributes == 0U) {
|
if ((create_options & FILE_DELETE_ON_CLOSE) != 0U) {
|
||||||
attributes = FILE_ATTRIBUTE_NORMAL;
|
attributes |= FILE_FLAG_DELETE_ON_CLOSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *handle = ::CreateFileW(
|
attributes |=
|
||||||
file_path.c_str(), granted_access,
|
((create_options & FILE_DIRECTORY_FILE) == 0U ? FILE_ATTRIBUTE_ARCHIVE
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
|
: FILE_ATTRIBUTE_DIRECTORY);
|
||||||
CREATE_NEW, static_cast<DWORD>(create_flags) | attributes, nullptr);
|
auto *handle =
|
||||||
|
::CreateFileW(file_path.c_str(), granted_access,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||||
|
nullptr, CREATE_NEW, attributes, nullptr);
|
||||||
if (handle != INVALID_HANDLE_VALUE) {
|
if (handle != INVALID_HANDLE_VALUE) {
|
||||||
*file_desc = reinterpret_cast<PVOID>(handle);
|
*file_desc = reinterpret_cast<PVOID>(handle);
|
||||||
normalized_name = utils::string::to_utf8(file_name);
|
normalized_name = utils::string::to_utf8(file_name);
|
||||||
set_open_info(*file_desc,
|
set_open_info(*file_desc, open_info{
|
||||||
open_info{0, "", nullptr, utils::string::to_utf8(file_path)});
|
"",
|
||||||
|
nullptr,
|
||||||
|
{},
|
||||||
|
utils::string::to_utf8(file_path),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ret =
|
auto ret =
|
||||||
(handle == INVALID_HANDLE_VALUE)
|
(handle == INVALID_HANDLE_VALUE)
|
||||||
? FspNtStatusFromWin32(::GetLastError())
|
? FspNtStatusFromWin32(::GetLastError())
|
||||||
: populate_file_info(construct_api_path(get_open_file_path(handle)),
|
: populate_file_info(construct_api_path(get_open_file_path(handle)),
|
||||||
@ -1062,7 +1066,7 @@ auto remote_server::winfsp_get_security_by_name(PWSTR file_name,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = utils::string::from_utf8(utils::path::combine(
|
auto file_path = utils::string::from_utf8(utils::path::combine(
|
||||||
mount_location_, {utils::string::to_utf8(file_name)}));
|
mount_location_, {utils::string::to_utf8(file_name)}));
|
||||||
|
|
||||||
auto ret = STATUS_BUFFER_OVERFLOW;
|
auto ret = STATUS_BUFFER_OVERFLOW;
|
||||||
@ -1076,13 +1080,14 @@ auto remote_server::winfsp_get_security_by_name(PWSTR file_name,
|
|||||||
descriptor_size);
|
descriptor_size);
|
||||||
if ((ret == STATUS_SUCCESS) && (descriptor_size != nullptr)) {
|
if ((ret == STATUS_SUCCESS) && (descriptor_size != nullptr)) {
|
||||||
ULONG str_size{};
|
ULONG str_size{};
|
||||||
const auto security_info =
|
auto security_info =
|
||||||
OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
|
OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
|
||||||
DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
|
DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
|
||||||
LPWSTR str{};
|
LPWSTR str{};
|
||||||
if (::ConvertSecurityDescriptorToStringSecurityDescriptorW(
|
if (::ConvertSecurityDescriptorToStringSecurityDescriptorW(
|
||||||
descriptor, SDDL_REVISION_1, security_info, &str, &str_size) !=
|
descriptor, SDDL_REVISION_1,
|
||||||
0) {
|
static_cast<SECURITY_INFORMATION>(security_info), &str,
|
||||||
|
&str_size) != 0) {
|
||||||
string_descriptor = std::wstring(str, wcslen(str));
|
string_descriptor = std::wstring(str, wcslen(str));
|
||||||
::LocalFree(str);
|
::LocalFree(str);
|
||||||
} else {
|
} else {
|
||||||
@ -1124,7 +1129,7 @@ auto remote_server::winfsp_open(PWSTR file_name, UINT32 create_options,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto file_path = utils::string::from_utf8(utils::path::combine(
|
auto file_path = utils::string::from_utf8(utils::path::combine(
|
||||||
mount_location_, {utils::string::to_utf8(file_name)}));
|
mount_location_, {utils::string::to_utf8(file_name)}));
|
||||||
|
|
||||||
auto create_flags = FILE_FLAG_BACKUP_SEMANTICS;
|
auto create_flags = FILE_FLAG_BACKUP_SEMANTICS;
|
||||||
@ -1139,11 +1144,15 @@ auto remote_server::winfsp_open(PWSTR file_name, UINT32 create_options,
|
|||||||
if (handle != INVALID_HANDLE_VALUE) {
|
if (handle != INVALID_HANDLE_VALUE) {
|
||||||
*file_desc = reinterpret_cast<PVOID>(handle);
|
*file_desc = reinterpret_cast<PVOID>(handle);
|
||||||
normalized_name = utils::string::to_utf8(file_name);
|
normalized_name = utils::string::to_utf8(file_name);
|
||||||
set_open_info(*file_desc,
|
set_open_info(*file_desc, open_info{
|
||||||
open_info{0, "", nullptr, utils::string::to_utf8(file_path)});
|
"",
|
||||||
|
nullptr,
|
||||||
|
{},
|
||||||
|
utils::string::to_utf8(file_path),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto ret =
|
auto ret =
|
||||||
(handle == INVALID_HANDLE_VALUE)
|
(handle == INVALID_HANDLE_VALUE)
|
||||||
? FspNtStatusFromWin32(::GetLastError())
|
? FspNtStatusFromWin32(::GetLastError())
|
||||||
: populate_file_info(construct_api_path(get_open_file_path(handle)),
|
: populate_file_info(construct_api_path(get_open_file_path(handle)),
|
||||||
@ -1163,35 +1172,25 @@ auto remote_server::winfsp_overwrite(PVOID file_desc, UINT32 attributes,
|
|||||||
auto *handle = reinterpret_cast<HANDLE>(file_desc);
|
auto *handle = reinterpret_cast<HANDLE>(file_desc);
|
||||||
auto ret = has_open_info(handle, STATUS_INVALID_HANDLE);
|
auto ret = has_open_info(handle, STATUS_INVALID_HANDLE);
|
||||||
if (ret == STATUS_SUCCESS) {
|
if (ret == STATUS_SUCCESS) {
|
||||||
|
attributes |= FILE_ATTRIBUTE_ARCHIVE;
|
||||||
|
|
||||||
if (replace_attributes != 0U) {
|
if (replace_attributes != 0U) {
|
||||||
if (attributes == 0U) {
|
|
||||||
attributes = FILE_ATTRIBUTE_NORMAL;
|
|
||||||
}
|
|
||||||
FILE_BASIC_INFO basic_info{};
|
FILE_BASIC_INFO basic_info{};
|
||||||
basic_info.FileAttributes = attributes;
|
basic_info.FileAttributes = attributes;
|
||||||
if (::SetFileInformationByHandle(handle, FileBasicInfo, &basic_info,
|
if (::SetFileInformationByHandle(handle, FileBasicInfo, &basic_info,
|
||||||
sizeof(FILE_BASIC_INFO)) == 0) {
|
sizeof(FILE_BASIC_INFO)) == 0) {
|
||||||
ret = FspNtStatusFromWin32(::GetLastError());
|
ret = FspNtStatusFromWin32(::GetLastError());
|
||||||
}
|
}
|
||||||
} else if (attributes != 0U) {
|
|
||||||
FILE_ATTRIBUTE_TAG_INFO tag_info{};
|
|
||||||
if (::GetFileInformationByHandleEx(
|
|
||||||
handle, FileAttributeTagInfo, &tag_info,
|
|
||||||
sizeof(FILE_ATTRIBUTE_TAG_INFO)) == 0) {
|
|
||||||
ret = FspNtStatusFromWin32(::GetLastError());
|
|
||||||
} else {
|
} else {
|
||||||
FILE_BASIC_INFO basic_info{};
|
FILE_ATTRIBUTE_TAG_INFO tag_info{};
|
||||||
basic_info.FileAttributes =
|
if (::GetFileInformationByHandleEx(handle, FileAttributeTagInfo,
|
||||||
attributes | (tag_info.FileAttributes &
|
&tag_info,
|
||||||
static_cast<UINT32>(~FILE_ATTRIBUTE_NORMAL));
|
sizeof(FILE_ATTRIBUTE_TAG_INFO))) {
|
||||||
if ((basic_info.FileAttributes != tag_info.FileAttributes)) {
|
attributes |= tag_info.FileAttributes;
|
||||||
if (::SetFileInformationByHandle(handle, FileBasicInfo, &basic_info,
|
} else {
|
||||||
sizeof(FILE_BASIC_INFO)) == 0) {
|
|
||||||
ret = FspNtStatusFromWin32(::GetLastError());
|
ret = FspNtStatusFromWin32(::GetLastError());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret == STATUS_SUCCESS) {
|
if (ret == STATUS_SUCCESS) {
|
||||||
FILE_ALLOCATION_INFO allocationInfo{};
|
FILE_ALLOCATION_INFO allocationInfo{};
|
||||||
@ -1248,7 +1247,7 @@ auto remote_server::winfsp_read_directory(PVOID file_desc, PWSTR /*pattern*/,
|
|||||||
|
|
||||||
open_info ofi{};
|
open_info ofi{};
|
||||||
if (get_open_info(file_desc, ofi)) {
|
if (get_open_info(file_desc, ofi)) {
|
||||||
const auto api_path =
|
auto api_path =
|
||||||
utils::path::create_api_path(ofi.path.substr(mount_location_.size()));
|
utils::path::create_api_path(ofi.path.substr(mount_location_.size()));
|
||||||
directory_iterator iter(drive_.get_directory_items(api_path));
|
directory_iterator iter(drive_.get_directory_items(api_path));
|
||||||
auto offset = marker == nullptr
|
auto offset = marker == nullptr
|
||||||
@ -1274,14 +1273,13 @@ auto remote_server::winfsp_rename(PVOID /*file_desc*/, PWSTR file_name,
|
|||||||
-> packet::error_type {
|
-> packet::error_type {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto from_path = utils::string::from_utf8(utils::path::combine(
|
auto from_path = utils::string::from_utf8(utils::path::combine(
|
||||||
mount_location_, {utils::string::to_utf8(file_name)}));
|
mount_location_, {utils::string::to_utf8(file_name)}));
|
||||||
const auto to_path = utils::string::from_utf8(utils::path::combine(
|
auto to_path = utils::string::from_utf8(utils::path::combine(
|
||||||
mount_location_, {utils::string::to_utf8(new_file_name)}));
|
mount_location_, {utils::string::to_utf8(new_file_name)}));
|
||||||
const auto ret =
|
auto ret = ::MoveFileExW(
|
||||||
::MoveFileExW(from_path.c_str(), to_path.c_str(),
|
from_path.c_str(), to_path.c_str(),
|
||||||
replace_if_exists == 0U ? 0 : MOVEFILE_REPLACE_EXISTING) !=
|
replace_if_exists == 0U ? 0 : MOVEFILE_REPLACE_EXISTING) != 0
|
||||||
0
|
|
||||||
? STATUS_SUCCESS
|
? STATUS_SUCCESS
|
||||||
: FspNtStatusFromWin32(::GetLastError());
|
: FspNtStatusFromWin32(::GetLastError());
|
||||||
|
|
||||||
|
@ -41,20 +41,19 @@ namespace repertory::remote_winfsp {
|
|||||||
remote_winfsp_drive::winfsp_service::winfsp_service(
|
remote_winfsp_drive::winfsp_service::winfsp_service(
|
||||||
lock_data &lock, remote_winfsp_drive &drive,
|
lock_data &lock, remote_winfsp_drive &drive,
|
||||||
std::vector<std::string> drive_args, app_config &config)
|
std::vector<std::string> drive_args, app_config &config)
|
||||||
: Service(&(L"RepertoryRemote_" +
|
: Service(std::wstring{REPERTORY_W}.data()),
|
||||||
utils::string::from_utf8(lock.get_unique_id()))[0U]),
|
|
||||||
config_(config),
|
config_(config),
|
||||||
lock_(lock),
|
|
||||||
drive_(drive),
|
drive_(drive),
|
||||||
drive_args_(std::move(drive_args)),
|
drive_args_(std::move(drive_args)),
|
||||||
host_(drive) {}
|
host_(drive),
|
||||||
|
lock_(lock) {}
|
||||||
|
|
||||||
auto remote_winfsp_drive::winfsp_service::OnStart(ULONG, PWSTR *) -> NTSTATUS {
|
auto remote_winfsp_drive::winfsp_service::OnStart(ULONG, PWSTR *) -> NTSTATUS {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
const auto mount_location = utils::string::to_lower(utils::path::absolute(
|
auto mount_location = utils::string::to_lower(utils::path::absolute(
|
||||||
(drive_args_.size() > 1U) ? drive_args_.at(1U) : ""));
|
(drive_args_.size() > 1U) ? drive_args_.at(1U) : ""));
|
||||||
const auto drive_letter =
|
auto drive_letter =
|
||||||
((mount_location.size() == 2U) ||
|
((mount_location.size() == 2U) ||
|
||||||
((mount_location.size() == 3U) && (mount_location.at(2U) == '\\'))) &&
|
((mount_location.size() == 3U) && (mount_location.at(2U) == '\\'))) &&
|
||||||
(mount_location.at(1U) == ':');
|
(mount_location.at(1U) == ':');
|
||||||
@ -115,8 +114,8 @@ auto remote_winfsp_drive::CanDelete(PVOID /*file_node*/, PVOID file_desc,
|
|||||||
|
|
||||||
VOID remote_winfsp_drive::Cleanup(PVOID /*file_node*/, PVOID file_desc,
|
VOID remote_winfsp_drive::Cleanup(PVOID /*file_node*/, PVOID file_desc,
|
||||||
PWSTR file_name, ULONG flags) {
|
PWSTR file_name, ULONG flags) {
|
||||||
BOOLEAN was_closed{};
|
BOOLEAN was_deleted{};
|
||||||
remote_instance_->winfsp_cleanup(file_desc, file_name, flags, was_closed);
|
remote_instance_->winfsp_cleanup(file_desc, file_name, flags, was_deleted);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID remote_winfsp_drive::Close(PVOID /*file_node*/, PVOID file_desc) {
|
VOID remote_winfsp_drive::Close(PVOID /*file_node*/, PVOID file_desc) {
|
||||||
@ -137,7 +136,7 @@ auto remote_winfsp_drive::Create(PWSTR file_name, UINT32 create_options,
|
|||||||
file_desc, &fi, normalized_name, exists);
|
file_desc, &fi, normalized_name, exists);
|
||||||
if (ret == STATUS_SUCCESS) {
|
if (ret == STATUS_SUCCESS) {
|
||||||
set_file_info(ofi->FileInfo, fi);
|
set_file_info(ofi->FileInfo, fi);
|
||||||
const auto file_path = utils::string::from_utf8(normalized_name);
|
auto file_path = utils::string::from_utf8(normalized_name);
|
||||||
wcsncpy(ofi->NormalizedName, file_path.data(), wcslen(file_path.c_str()));
|
wcsncpy(ofi->NormalizedName, file_path.data(), wcslen(file_path.c_str()));
|
||||||
ofi->NormalizedNameSize =
|
ofi->NormalizedNameSize =
|
||||||
static_cast<UINT16>(wcslen(file_path.c_str()) * sizeof(WCHAR));
|
static_cast<UINT16>(wcslen(file_path.c_str()) * sizeof(WCHAR));
|
||||||
@ -196,8 +195,7 @@ auto remote_winfsp_drive::GetVolumeInfo(VolumeInfo *volume_info) -> NTSTATUS {
|
|||||||
auto ret = remote_instance_->winfsp_get_volume_info(
|
auto ret = remote_instance_->winfsp_get_volume_info(
|
||||||
volume_info->TotalSize, volume_info->FreeSize, volume_label);
|
volume_info->TotalSize, volume_info->FreeSize, volume_label);
|
||||||
if (ret == STATUS_SUCCESS) {
|
if (ret == STATUS_SUCCESS) {
|
||||||
const auto byte_size =
|
auto byte_size = static_cast<UINT16>(volume_label.size() * sizeof(WCHAR));
|
||||||
static_cast<UINT16>(volume_label.size() * sizeof(WCHAR));
|
|
||||||
wcscpy_s(&volume_info->VolumeLabel[0U], 32,
|
wcscpy_s(&volume_info->VolumeLabel[0U], 32,
|
||||||
utils::string::from_utf8(volume_label).c_str());
|
utils::string::from_utf8(volume_label).c_str());
|
||||||
volume_info->VolumeLabelLength =
|
volume_info->VolumeLabelLength =
|
||||||
@ -213,20 +211,21 @@ auto remote_winfsp_drive::Init(PVOID host) -> NTSTATUS {
|
|||||||
&(L"\\repertory\\" +
|
&(L"\\repertory\\" +
|
||||||
std::wstring(file_system_host->FileSystemName()).substr(0U, 1U))[0U]);
|
std::wstring(file_system_host->FileSystemName()).substr(0U, 1U))[0U]);
|
||||||
}
|
}
|
||||||
file_system_host->SetFileSystemName(std::wstring{REPERTORY_W}.data());
|
|
||||||
|
file_system_host->SetCasePreservedNames(TRUE);
|
||||||
|
file_system_host->SetCaseSensitiveSearch(TRUE);
|
||||||
|
file_system_host->SetFileInfoTimeout(1000);
|
||||||
file_system_host->SetFlushAndPurgeOnCleanup(TRUE);
|
file_system_host->SetFlushAndPurgeOnCleanup(TRUE);
|
||||||
|
file_system_host->SetMaxComponentLength(255U);
|
||||||
|
file_system_host->SetNamedStreams(FALSE);
|
||||||
|
file_system_host->SetPassQueryDirectoryPattern(FALSE);
|
||||||
|
file_system_host->SetPersistentAcls(FALSE);
|
||||||
|
file_system_host->SetPostCleanupWhenModifiedOnly(TRUE);
|
||||||
file_system_host->SetReparsePoints(FALSE);
|
file_system_host->SetReparsePoints(FALSE);
|
||||||
file_system_host->SetReparsePointsAccessCheck(FALSE);
|
file_system_host->SetReparsePointsAccessCheck(FALSE);
|
||||||
file_system_host->SetSectorSize(WINFSP_ALLOCATION_UNIT);
|
file_system_host->SetSectorSize(WINFSP_ALLOCATION_UNIT);
|
||||||
file_system_host->SetSectorsPerAllocationUnit(1);
|
file_system_host->SetSectorsPerAllocationUnit(1);
|
||||||
file_system_host->SetFileInfoTimeout(1000);
|
|
||||||
file_system_host->SetCaseSensitiveSearch(FALSE);
|
|
||||||
file_system_host->SetCasePreservedNames(TRUE);
|
|
||||||
file_system_host->SetNamedStreams(FALSE);
|
|
||||||
file_system_host->SetUnicodeOnDisk(TRUE);
|
file_system_host->SetUnicodeOnDisk(TRUE);
|
||||||
file_system_host->SetPersistentAcls(FALSE);
|
|
||||||
file_system_host->SetPostCleanupWhenModifiedOnly(TRUE);
|
|
||||||
file_system_host->SetPassQueryDirectoryPattern(FALSE);
|
|
||||||
file_system_host->SetVolumeCreationTime(utils::time::get_time_now());
|
file_system_host->SetVolumeCreationTime(utils::time::get_time_now());
|
||||||
file_system_host->SetVolumeSerialNumber(0);
|
file_system_host->SetVolumeSerialNumber(0);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
@ -236,10 +235,10 @@ auto remote_winfsp_drive::mount(const std::vector<std::string> &drive_args)
|
|||||||
-> int {
|
-> int {
|
||||||
std::vector<std::string> parsed_drive_args;
|
std::vector<std::string> parsed_drive_args;
|
||||||
|
|
||||||
const auto force_no_console = utils::collection::includes(drive_args, "-nc");
|
auto force_no_console = utils::collection::includes(drive_args, "-nc");
|
||||||
|
|
||||||
auto enable_console = false;
|
auto enable_console = false;
|
||||||
for (const auto &arg : drive_args) {
|
for (auto &&arg : drive_args) {
|
||||||
if (arg == "-f") {
|
if (arg == "-f") {
|
||||||
if (not force_no_console) {
|
if (not force_no_console) {
|
||||||
enable_console = true;
|
enable_console = true;
|
||||||
@ -289,7 +288,7 @@ auto remote_winfsp_drive::Open(PWSTR file_name, UINT32 create_options,
|
|||||||
file_desc, &fi, normalize_name);
|
file_desc, &fi, normalize_name);
|
||||||
if (ret == STATUS_SUCCESS) {
|
if (ret == STATUS_SUCCESS) {
|
||||||
set_file_info(ofi->FileInfo, fi);
|
set_file_info(ofi->FileInfo, fi);
|
||||||
const auto file_path = utils::string::from_utf8(normalize_name);
|
auto file_path = utils::string::from_utf8(normalize_name);
|
||||||
wcsncpy(ofi->NormalizedName, file_path.data(), wcslen(file_path.c_str()));
|
wcsncpy(ofi->NormalizedName, file_path.data(), wcslen(file_path.c_str()));
|
||||||
ofi->NormalizedNameSize =
|
ofi->NormalizedNameSize =
|
||||||
static_cast<UINT16>(wcslen(file_path.c_str()) * sizeof(WCHAR));
|
static_cast<UINT16>(wcslen(file_path.c_str()) * sizeof(WCHAR));
|
||||||
@ -303,27 +302,27 @@ auto remote_winfsp_drive::Overwrite(PVOID /*file_node*/, PVOID file_desc,
|
|||||||
BOOLEAN replace_attributes,
|
BOOLEAN replace_attributes,
|
||||||
UINT64 allocation_size, FileInfo *file_info)
|
UINT64 allocation_size, FileInfo *file_info)
|
||||||
-> NTSTATUS {
|
-> NTSTATUS {
|
||||||
remote::file_info fi{};
|
remote::file_info info{};
|
||||||
auto ret = remote_instance_->winfsp_overwrite(
|
auto ret = remote_instance_->winfsp_overwrite(
|
||||||
file_desc, attributes, replace_attributes, allocation_size, &fi);
|
file_desc, attributes, replace_attributes, allocation_size, &info);
|
||||||
set_file_info(*file_info, fi);
|
set_file_info(*file_info, info);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void remote_winfsp_drive::populate_file_info(const json &item,
|
void remote_winfsp_drive::populate_file_info(const json &item,
|
||||||
FSP_FSCTL_FILE_INFO &file_info) {
|
FSP_FSCTL_FILE_INFO &file_info) {
|
||||||
const auto di = directory_item::from_json(item);
|
auto dir_item = item.get<directory_item>();
|
||||||
file_info.FileSize = di.directory ? 0 : di.size;
|
file_info.FileSize = dir_item.directory ? 0 : dir_item.size;
|
||||||
file_info.AllocationSize =
|
file_info.AllocationSize =
|
||||||
utils::divide_with_ceiling(file_info.FileSize, WINFSP_ALLOCATION_UNIT) *
|
utils::divide_with_ceiling(file_info.FileSize, WINFSP_ALLOCATION_UNIT) *
|
||||||
WINFSP_ALLOCATION_UNIT;
|
WINFSP_ALLOCATION_UNIT;
|
||||||
file_info.ChangeTime = utils::get_changed_time_from_meta(di.meta);
|
file_info.ChangeTime = utils::get_changed_time_from_meta(dir_item.meta);
|
||||||
file_info.CreationTime = utils::get_creation_time_from_meta(di.meta);
|
file_info.CreationTime = utils::get_creation_time_from_meta(dir_item.meta);
|
||||||
file_info.FileAttributes = utils::get_attributes_from_meta(di.meta);
|
file_info.FileAttributes = utils::get_attributes_from_meta(dir_item.meta);
|
||||||
file_info.HardLinks = 0;
|
file_info.HardLinks = 0;
|
||||||
file_info.IndexNumber = 0;
|
file_info.IndexNumber = 0;
|
||||||
file_info.LastAccessTime = utils::get_accessed_time_from_meta(di.meta);
|
file_info.LastAccessTime = utils::get_accessed_time_from_meta(dir_item.meta);
|
||||||
file_info.LastWriteTime = utils::get_written_time_from_meta(di.meta);
|
file_info.LastWriteTime = utils::get_written_time_from_meta(dir_item.meta);
|
||||||
file_info.ReparseTag = 0;
|
file_info.ReparseTag = 0;
|
||||||
file_info.EaSize = 0;
|
file_info.EaSize = 0;
|
||||||
}
|
}
|
||||||
@ -353,15 +352,15 @@ auto remote_winfsp_drive::ReadDirectory(PVOID /*file_node*/, PVOID file_desc,
|
|||||||
directory_buffer, static_cast<BOOLEAN>(nullptr == marker),
|
directory_buffer, static_cast<BOOLEAN>(nullptr == marker),
|
||||||
&ret)) {
|
&ret)) {
|
||||||
auto item_found = false;
|
auto item_found = false;
|
||||||
for (const auto &item : item_list) {
|
for (auto &&item : item_list) {
|
||||||
const auto item_path = item["path"].get<std::string>();
|
auto item_path = item["path"].get<std::string>();
|
||||||
const auto display_name = utils::string::from_utf8(
|
auto display_name = utils::string::from_utf8(
|
||||||
utils::path::strip_to_file_name(item_path));
|
utils::path::strip_to_file_name(item_path));
|
||||||
if (not marker || (marker && item_found)) {
|
if (not marker || (marker && item_found)) {
|
||||||
// if (not utils::path::is_ads_file_path(item_path)) {
|
// if (not utils::path::is_ads_file_path(item_path)) {
|
||||||
union {
|
union {
|
||||||
UINT8 B[FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) +
|
UINT8 B[FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) +
|
||||||
((MAX_PATH + 1) * sizeof(WCHAR))];
|
((repertory::max_path_length + 1U) * sizeof(WCHAR))];
|
||||||
FSP_FSCTL_DIR_INFO D;
|
FSP_FSCTL_DIR_INFO D;
|
||||||
} directory_info_buffer;
|
} directory_info_buffer;
|
||||||
|
|
||||||
@ -369,7 +368,8 @@ auto remote_winfsp_drive::ReadDirectory(PVOID /*file_node*/, PVOID file_desc,
|
|||||||
::ZeroMemory(directory_info, sizeof(*directory_info));
|
::ZeroMemory(directory_info, sizeof(*directory_info));
|
||||||
directory_info->Size = static_cast<UINT16>(
|
directory_info->Size = static_cast<UINT16>(
|
||||||
FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) +
|
FIELD_OFFSET(FSP_FSCTL_DIR_INFO, FileNameBuf) +
|
||||||
(std::min(static_cast<size_t>(MAX_PATH), display_name.size()) *
|
(std::min(static_cast<size_t>(repertory::max_path_length),
|
||||||
|
display_name.size()) *
|
||||||
sizeof(WCHAR)));
|
sizeof(WCHAR)));
|
||||||
|
|
||||||
if (not item["meta"].empty() ||
|
if (not item["meta"].empty() ||
|
||||||
@ -377,8 +377,8 @@ auto remote_winfsp_drive::ReadDirectory(PVOID /*file_node*/, PVOID file_desc,
|
|||||||
populate_file_info(item, directory_info->FileInfo);
|
populate_file_info(item, directory_info->FileInfo);
|
||||||
}
|
}
|
||||||
if (ret == STATUS_SUCCESS) {
|
if (ret == STATUS_SUCCESS) {
|
||||||
::wcscpy_s(&directory_info->FileNameBuf[0], MAX_PATH,
|
::wcscpy_s(&directory_info->FileNameBuf[0],
|
||||||
&display_name[0]);
|
repertory::max_path_length, &display_name[0]);
|
||||||
|
|
||||||
FspFileSystemFillDirectoryBuffer(directory_buffer, directory_info,
|
FspFileSystemFillDirectoryBuffer(directory_buffer, directory_info,
|
||||||
&ret);
|
&ret);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -24,7 +24,8 @@
|
|||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
auto event_level_from_string(std::string level) -> event_level {
|
auto event_level_from_string(std::string level, event_level default_level)
|
||||||
|
-> event_level {
|
||||||
level = utils::string::to_lower(level);
|
level = utils::string::to_lower(level);
|
||||||
if (level == "critical" || level == "event_level::critical") {
|
if (level == "critical" || level == "event_level::critical") {
|
||||||
return event_level::critical;
|
return event_level::critical;
|
||||||
@ -50,7 +51,7 @@ auto event_level_from_string(std::string level) -> event_level {
|
|||||||
return event_level::trace;
|
return event_level::trace;
|
||||||
}
|
}
|
||||||
|
|
||||||
return event_level::info;
|
return default_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto event_level_to_string(event_level level) -> std::string {
|
auto event_level_to_string(event_level level) -> std::string {
|
||||||
|
128
repertory/librepertory/src/file_manager/cache_size_mgr.cpp
Normal file
128
repertory/librepertory/src/file_manager/cache_size_mgr.cpp
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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 "file_manager/cache_size_mgr.hpp"
|
||||||
|
|
||||||
|
#include "app_config.hpp"
|
||||||
|
#include "events/event.hpp"
|
||||||
|
#include "events/event_system.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
unique_mutex_lock lock(mtx_);
|
||||||
|
if (cfg_ == nullptr) {
|
||||||
|
return api_error::cache_not_initialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache_size_ += size;
|
||||||
|
|
||||||
|
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 &&
|
||||||
|
cache_dir.count() > 1U) {
|
||||||
|
event_system::instance().raise<max_cache_size_reached>(cache_size_,
|
||||||
|
max_cache_size);
|
||||||
|
notify_.wait(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
notify_.notify_all();
|
||||||
|
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cache_size_mgr::initialize(app_config *cfg) {
|
||||||
|
if (cfg == nullptr) {
|
||||||
|
throw startup_exception("app_config must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_lock lock(mtx_);
|
||||||
|
cfg_ = cfg;
|
||||||
|
|
||||||
|
stop_requested_ = false;
|
||||||
|
|
||||||
|
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()));
|
||||||
|
}
|
||||||
|
|
||||||
|
cache_size_ = cache_dir.size(false);
|
||||||
|
|
||||||
|
notify_.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cache_size_mgr::shrink(std::uint64_t size) -> api_error {
|
||||||
|
mutex_lock lock(mtx_);
|
||||||
|
if (size == 0U) {
|
||||||
|
notify_.notify_all();
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cache_size_ >= size) {
|
||||||
|
cache_size_ -= size;
|
||||||
|
} else {
|
||||||
|
event_system::instance().raise<invalid_cache_size>(cache_size_, size);
|
||||||
|
cache_size_ = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
notify_.notify_all();
|
||||||
|
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cache_size_mgr::size() const -> std::uint64_t {
|
||||||
|
mutex_lock lock(mtx_);
|
||||||
|
return cache_size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cache_size_mgr::stop() {
|
||||||
|
if (stop_requested_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_requested_ = true;
|
||||||
|
|
||||||
|
mutex_lock lock(mtx_);
|
||||||
|
notify_.notify_all();
|
||||||
|
}
|
||||||
|
} // namespace repertory
|
63
repertory/librepertory/src/file_manager/direct_open_file.cpp
Normal file
63
repertory/librepertory/src/file_manager/direct_open_file.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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 "file_manager/direct_open_file.hpp"
|
||||||
|
|
||||||
|
#include "file_manager/open_file_base.hpp"
|
||||||
|
#include "providers/i_provider.hpp"
|
||||||
|
#include "types/repertory.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
direct_open_file::direct_open_file(std::uint64_t chunk_size,
|
||||||
|
std::uint8_t chunk_timeout,
|
||||||
|
filesystem_item fsi, i_provider &provider)
|
||||||
|
: ring_buffer_base(chunk_size, chunk_timeout, fsi, provider,
|
||||||
|
min_ring_size, true) {}
|
||||||
|
|
||||||
|
direct_open_file::~direct_open_file() {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto direct_open_file::on_check_start() -> bool {
|
||||||
|
return (get_file_size() == 0U || has_reader_thread());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto direct_open_file::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 {
|
||||||
|
auto &buffer = ring_data_.at(chunk % get_ring_size());
|
||||||
|
auto begin =
|
||||||
|
std::next(buffer.begin(), static_cast<std::int64_t>(read_offset));
|
||||||
|
auto end = std::next(begin, static_cast<std::int64_t>(read_size));
|
||||||
|
data.insert(data.end(), begin, end);
|
||||||
|
bytes_read = read_size;
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto direct_open_file::use_buffer(std::size_t chunk,
|
||||||
|
std::function<api_error(data_buffer &)> func)
|
||||||
|
-> api_error {
|
||||||
|
return func(ring_data_.at(chunk % get_ring_size()));
|
||||||
|
}
|
||||||
|
} // namespace repertory
|
File diff suppressed because it is too large
Load Diff
@ -21,18 +21,17 @@
|
|||||||
*/
|
*/
|
||||||
#include "file_manager/open_file.hpp"
|
#include "file_manager/open_file.hpp"
|
||||||
|
|
||||||
|
#include "file_manager/cache_size_mgr.hpp"
|
||||||
#include "file_manager/events.hpp"
|
#include "file_manager/events.hpp"
|
||||||
|
#include "file_manager/file_manager.hpp"
|
||||||
#include "file_manager/i_upload_manager.hpp"
|
#include "file_manager/i_upload_manager.hpp"
|
||||||
#include "platform/platform.hpp"
|
#include "platform/platform.hpp"
|
||||||
#include "providers/i_provider.hpp"
|
#include "providers/i_provider.hpp"
|
||||||
#include "types/repertory.hpp"
|
#include "types/repertory.hpp"
|
||||||
#include "types/startup_exception.hpp"
|
|
||||||
#include "utils/common.hpp"
|
#include "utils/common.hpp"
|
||||||
#include "utils/error_utils.hpp"
|
#include "utils/error_utils.hpp"
|
||||||
#include "utils/file_utils.hpp"
|
|
||||||
#include "utils/path.hpp"
|
#include "utils/path.hpp"
|
||||||
#include "utils/time.hpp"
|
#include "utils/time.hpp"
|
||||||
#include "utils/utils.hpp"
|
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
open_file::open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
open_file::open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||||
@ -61,75 +60,246 @@ open_file::open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
|||||||
i_provider &provider,
|
i_provider &provider,
|
||||||
std::optional<boost::dynamic_bitset<>> read_state,
|
std::optional<boost::dynamic_bitset<>> read_state,
|
||||||
i_upload_manager &mgr)
|
i_upload_manager &mgr)
|
||||||
: open_file_base(chunk_size, chunk_timeout, fsi, open_data, provider),
|
: open_file_base(chunk_size, chunk_timeout, fsi, open_data, provider,
|
||||||
|
false),
|
||||||
mgr_(mgr) {
|
mgr_(mgr) {
|
||||||
if (fsi_.directory && read_state.has_value()) {
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
throw startup_exception("cannot resume a directory|" + fsi.api_path);
|
|
||||||
|
if (fsi.directory) {
|
||||||
|
if (read_state.has_value()) {
|
||||||
|
utils::error::raise_api_path_error(
|
||||||
|
function_name, fsi.api_path, fsi.source_path,
|
||||||
|
fmt::format("cannot resume a directory|sp|", fsi.api_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not fsi.directory) {
|
|
||||||
nf_ = utils::file::file::open_or_create_file(fsi.source_path,
|
nf_ = utils::file::file::open_or_create_file(fsi.source_path,
|
||||||
provider_.is_direct_only());
|
get_provider().is_read_only());
|
||||||
set_api_error(*nf_ ? api_error::success : api_error::os_error);
|
set_api_error(*nf_ ? api_error::success : api_error::os_error);
|
||||||
if (get_api_error() == api_error::success) {
|
if (get_api_error() != api_error::success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (read_state.has_value()) {
|
if (read_state.has_value()) {
|
||||||
read_state_ = read_state.value();
|
read_state_ = read_state.value();
|
||||||
set_modified();
|
set_modified();
|
||||||
} else if (fsi_.size > 0U) {
|
allocated = true;
|
||||||
read_state_.resize(static_cast<std::size_t>(utils::divide_with_ceiling(
|
return;
|
||||||
fsi_.size, chunk_size)),
|
}
|
||||||
|
|
||||||
|
if (fsi.size == 0U) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
read_state_.resize(static_cast<std::size_t>(
|
||||||
|
utils::divide_with_ceiling(fsi.size, chunk_size)),
|
||||||
false);
|
false);
|
||||||
|
|
||||||
auto file_size = nf_->size();
|
auto file_size = nf_->size();
|
||||||
if (provider_.is_direct_only() || file_size == fsi.size) {
|
if (not file_size.has_value()) {
|
||||||
read_state_.set(0U, read_state_.size(), true);
|
utils::error::raise_api_path_error(
|
||||||
} else if (not nf_->truncate(fsi.size)) {
|
function_name, fsi.api_path, fsi.source_path,
|
||||||
|
utils::get_last_error_code(), "failed to get file size");
|
||||||
set_api_error(api_error::os_error);
|
set_api_error(api_error::os_error);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (get_provider().is_read_only() || file_size.value() == fsi.size) {
|
||||||
|
read_state_.set(0U, read_state_.size(), true);
|
||||||
|
allocated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_api_error() != api_error::success && *nf_) {
|
if (get_api_error() != api_error::success && *nf_) {
|
||||||
nf_->close();
|
nf_->close();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open_file::~open_file() { close(); }
|
open_file::~open_file() { close(); }
|
||||||
|
|
||||||
|
auto open_file::adjust_cache_size(std::uint64_t file_size,
|
||||||
|
bool shrink) -> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
if (file_size == get_file_size()) {
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_size > get_file_size()) {
|
||||||
|
auto size = file_size - get_file_size();
|
||||||
|
auto res = shrink ? cache_size_mgr::instance().shrink(size)
|
||||||
|
: cache_size_mgr::instance().expand(size);
|
||||||
|
if (res == api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::error::raise_api_path_error(
|
||||||
|
function_name, get_api_path(), get_source_path(), res,
|
||||||
|
fmt::format("failed to {} cache|size|{}",
|
||||||
|
(shrink ? "shrink" : "expand"), size));
|
||||||
|
return set_api_error(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto size = get_file_size() - file_size;
|
||||||
|
auto res = shrink ? cache_size_mgr::instance().expand(size)
|
||||||
|
: cache_size_mgr::instance().shrink(size);
|
||||||
|
if (res == api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
utils::error::raise_api_path_error(
|
||||||
|
function_name, get_api_path(), get_source_path(), res,
|
||||||
|
fmt::format("failed to {} cache|size|{}", (shrink ? "expand" : "shrink"),
|
||||||
|
size));
|
||||||
|
return set_api_error(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto open_file::check_start() -> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
unique_recur_mutex_lock file_lock(get_mutex());
|
||||||
|
if (allocated) {
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto file_size = nf_->size();
|
||||||
|
if (not file_size.has_value()) {
|
||||||
|
utils::error::raise_api_path_error(
|
||||||
|
function_name, get_api_path(), get_source_path(),
|
||||||
|
utils::get_last_error_code(), "failed to get file size");
|
||||||
|
return set_api_error(api_error::os_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_size.value() == get_file_size()) {
|
||||||
|
allocated = true;
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_lock.unlock();
|
||||||
|
auto res = adjust_cache_size(file_size.value(), true);
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
file_lock.lock();
|
||||||
|
|
||||||
|
if (not nf_->truncate(get_file_size())) {
|
||||||
|
utils::error::raise_api_path_error(
|
||||||
|
function_name, get_api_path(), get_source_path(),
|
||||||
|
utils::get_last_error_code(),
|
||||||
|
fmt::format("failed to truncate file|size|{}", get_file_size()));
|
||||||
|
return set_api_error(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
allocated = true;
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto open_file::close() -> bool {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
if (is_directory() || stop_requested_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_requested_ = true;
|
||||||
|
|
||||||
|
notify_io();
|
||||||
|
|
||||||
|
if (reader_thread_) {
|
||||||
|
reader_thread_->join();
|
||||||
|
reader_thread_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not open_file_base::close()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto read_state = get_read_state();
|
||||||
|
auto err = get_api_error();
|
||||||
|
if (err == api_error::success || err == api_error::download_incomplete ||
|
||||||
|
err == api_error::download_stopped) {
|
||||||
|
if (is_modified() && not read_state.all()) {
|
||||||
|
set_api_error(api_error::download_incomplete);
|
||||||
|
} else if (not is_modified() && (get_file_size() > 0U) &&
|
||||||
|
not read_state.all()) {
|
||||||
|
set_api_error(api_error::download_stopped);
|
||||||
|
}
|
||||||
|
|
||||||
|
err = get_api_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
nf_->close();
|
||||||
|
|
||||||
|
if (is_modified()) {
|
||||||
|
if (err == api_error::success) {
|
||||||
|
mgr_.queue_upload(*this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err == api_error::download_incomplete) {
|
||||||
|
mgr_.store_resume(*this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != api_error::success || read_state.all()) {
|
||||||
|
mgr_.remove_resume(get_api_path(), get_source_path());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err == api_error::success) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_manager::remove_source_and_shrink_cache(
|
||||||
|
get_api_path(), get_source_path(), get_file_size(), allocated);
|
||||||
|
|
||||||
|
auto parent = utils::path::get_parent_path(get_source_path());
|
||||||
|
set_source_path(utils::path::combine(parent, {utils::create_uuid_string()}));
|
||||||
|
|
||||||
|
auto res = get_provider().set_item_meta(get_api_path(), META_SOURCE,
|
||||||
|
get_source_path());
|
||||||
|
if (res != api_error::success) {
|
||||||
|
utils::error::raise_api_path_error(function_name, get_api_path(),
|
||||||
|
get_source_path(), res,
|
||||||
|
"failed to set new source path");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void open_file::download_chunk(std::size_t chunk, bool skip_active,
|
void open_file::download_chunk(std::size_t chunk, bool skip_active,
|
||||||
bool should_reset) {
|
bool should_reset) {
|
||||||
if (should_reset) {
|
if (should_reset) {
|
||||||
reset_timeout();
|
reset_timeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_recur_mutex_lock download_lock(file_mtx_);
|
unique_recur_mutex_lock rw_lock(rw_mtx_);
|
||||||
if ((get_api_error() == api_error::success) && (chunk < read_state_.size()) &&
|
auto read_state = get_read_state();
|
||||||
not read_state_[chunk]) {
|
if ((get_api_error() == api_error::success) && (chunk < read_state.size()) &&
|
||||||
if (active_downloads_.find(chunk) != active_downloads_.end()) {
|
not read_state[chunk]) {
|
||||||
if (not skip_active) {
|
if (get_active_downloads().find(chunk) != get_active_downloads().end()) {
|
||||||
auto active_download = active_downloads_.at(chunk);
|
if (skip_active) {
|
||||||
download_lock.unlock();
|
|
||||||
|
|
||||||
active_download->wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto data_offset = chunk * chunk_size_;
|
auto active_download = get_active_downloads().at(chunk);
|
||||||
const auto data_size =
|
rw_lock.unlock();
|
||||||
(chunk == read_state_.size() - 1U) ? last_chunk_size_ : chunk_size_;
|
|
||||||
if (active_downloads_.empty() && (read_state_.count() == 0U)) {
|
|
||||||
event_system::instance().raise<download_begin>(fsi_.api_path,
|
|
||||||
fsi_.source_path);
|
|
||||||
}
|
|
||||||
event_system::instance().raise<download_chunk_begin>(
|
|
||||||
fsi_.api_path, fsi_.source_path, chunk, read_state_.size(),
|
|
||||||
read_state_.count());
|
|
||||||
|
|
||||||
active_downloads_[chunk] = std::make_shared<download>();
|
active_download->wait();
|
||||||
download_lock.unlock();
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto data_offset = chunk * get_chunk_size();
|
||||||
|
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<download_begin>(get_api_path(),
|
||||||
|
get_source_path());
|
||||||
|
}
|
||||||
|
|
||||||
|
get_active_downloads()[chunk] = std::make_shared<download>();
|
||||||
|
rw_lock.unlock();
|
||||||
|
|
||||||
if (should_reset) {
|
if (should_reset) {
|
||||||
reset_timeout();
|
reset_timeout();
|
||||||
@ -138,28 +308,28 @@ void open_file::download_chunk(std::size_t chunk, bool skip_active,
|
|||||||
std::async(std::launch::async, [this, chunk, data_size, data_offset,
|
std::async(std::launch::async, [this, chunk, data_size, data_offset,
|
||||||
should_reset]() {
|
should_reset]() {
|
||||||
const auto notify_complete = [this, chunk, should_reset]() {
|
const auto notify_complete = [this, chunk, should_reset]() {
|
||||||
unique_recur_mutex_lock file_lock(file_mtx_);
|
auto state = get_read_state();
|
||||||
auto active_download = active_downloads_.at(chunk);
|
|
||||||
active_downloads_.erase(chunk);
|
unique_recur_mutex_lock lock(rw_mtx_);
|
||||||
event_system::instance().raise<download_chunk_end>(
|
auto active_download = get_active_downloads().at(chunk);
|
||||||
fsi_.api_path, fsi_.source_path, chunk, read_state_.size(),
|
get_active_downloads().erase(chunk);
|
||||||
read_state_.count(), get_api_error());
|
|
||||||
if (get_api_error() == api_error::success) {
|
if (get_api_error() == api_error::success) {
|
||||||
auto progress = (static_cast<double>(read_state_.count()) /
|
auto progress = (static_cast<double>(state.count()) /
|
||||||
static_cast<double>(read_state_.size()) * 100.0);
|
static_cast<double>(state.size())) *
|
||||||
|
100.0;
|
||||||
event_system::instance().raise<download_progress>(
|
event_system::instance().raise<download_progress>(
|
||||||
fsi_.api_path, fsi_.source_path, progress);
|
get_api_path(), get_source_path(), progress);
|
||||||
if (read_state_.all() && not notified_) {
|
if (state.all() && not notified_) {
|
||||||
notified_ = true;
|
notified_ = true;
|
||||||
event_system::instance().raise<download_end>(
|
event_system::instance().raise<download_end>(
|
||||||
fsi_.api_path, fsi_.source_path, get_api_error());
|
get_api_path(), get_source_path(), get_api_error());
|
||||||
}
|
}
|
||||||
} else if (not notified_) {
|
} else if (not notified_) {
|
||||||
notified_ = true;
|
notified_ = true;
|
||||||
event_system::instance().raise<download_end>(
|
event_system::instance().raise<download_end>(
|
||||||
fsi_.api_path, fsi_.source_path, get_api_error());
|
get_api_path(), get_source_path(), get_api_error());
|
||||||
}
|
}
|
||||||
file_lock.unlock();
|
lock.unlock();
|
||||||
|
|
||||||
active_download->notify(get_api_error());
|
active_download->notify(get_api_error());
|
||||||
|
|
||||||
@ -168,9 +338,9 @@ void open_file::download_chunk(std::size_t chunk, bool skip_active,
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
data_buffer data;
|
data_buffer buffer;
|
||||||
auto res = provider_.read_file_bytes(get_api_path(), data_size,
|
auto res = get_provider().read_file_bytes(
|
||||||
data_offset, data, stop_requested_);
|
get_api_path(), data_size, data_offset, buffer, stop_requested_);
|
||||||
if (res != api_error::success) {
|
if (res != api_error::success) {
|
||||||
set_api_error(res);
|
set_api_error(res);
|
||||||
notify_complete();
|
notify_complete();
|
||||||
@ -183,7 +353,7 @@ void open_file::download_chunk(std::size_t chunk, bool skip_active,
|
|||||||
|
|
||||||
res = do_io([&]() -> api_error {
|
res = do_io([&]() -> api_error {
|
||||||
std::size_t bytes_written{};
|
std::size_t bytes_written{};
|
||||||
if (not nf_->write(data, data_offset, &bytes_written)) {
|
if (not nf_->write(buffer, data_offset, &bytes_written)) {
|
||||||
return api_error::os_error;
|
return api_error::os_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,50 +368,50 @@ void open_file::download_chunk(std::size_t chunk, bool skip_active,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_recur_mutex_lock file_lock(file_mtx_);
|
set_read_state(chunk);
|
||||||
read_state_.set(chunk);
|
|
||||||
file_lock.unlock();
|
|
||||||
|
|
||||||
notify_complete();
|
notify_complete();
|
||||||
}).wait();
|
}).wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void open_file::download_range(std::size_t start_chunk_index,
|
void open_file::download_range(std::size_t begin_chunk, std::size_t end_chunk,
|
||||||
std::size_t end_chunk_index_inclusive,
|
|
||||||
bool should_reset) {
|
bool should_reset) {
|
||||||
for (std::size_t chunk = start_chunk_index;
|
for (std::size_t chunk = begin_chunk;
|
||||||
chunk <= end_chunk_index_inclusive; chunk++) {
|
(get_api_error() == api_error::success) && (chunk <= end_chunk);
|
||||||
|
++chunk) {
|
||||||
download_chunk(chunk, false, should_reset);
|
download_chunk(chunk, false, should_reset);
|
||||||
if (get_api_error() != api_error::success) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto open_file::get_allocated() const -> bool {
|
||||||
|
recur_mutex_lock file_lock(get_mutex());
|
||||||
|
return allocated;
|
||||||
|
}
|
||||||
|
|
||||||
auto open_file::get_read_state() const -> boost::dynamic_bitset<> {
|
auto open_file::get_read_state() const -> boost::dynamic_bitset<> {
|
||||||
recur_mutex_lock file_lock(file_mtx_);
|
recur_mutex_lock file_lock(get_mutex());
|
||||||
return read_state_;
|
return read_state_;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto open_file::get_read_state(std::size_t chunk) const -> bool {
|
auto open_file::get_read_state(std::size_t chunk) const -> bool {
|
||||||
recur_mutex_lock file_lock(file_mtx_);
|
return get_read_state()[chunk];
|
||||||
return read_state_[chunk];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto open_file::is_complete() const -> bool {
|
auto open_file::is_complete() const -> bool { return get_read_state().all(); }
|
||||||
recur_mutex_lock file_lock(file_mtx_);
|
|
||||||
return read_state_.all();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto open_file::native_operation(
|
auto open_file::native_operation(
|
||||||
i_open_file::native_operation_callback callback) -> api_error {
|
i_open_file::native_operation_callback callback) -> api_error {
|
||||||
unique_recur_mutex_lock file_lock(file_mtx_);
|
|
||||||
if (stop_requested_) {
|
if (stop_requested_) {
|
||||||
return api_error::download_stopped;
|
return set_api_error(api_error::download_stopped);
|
||||||
}
|
}
|
||||||
file_lock.unlock();
|
|
||||||
|
|
||||||
|
auto res = check_start();
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
unique_recur_mutex_lock rw_lock(rw_mtx_);
|
||||||
return do_io([&]() -> api_error { return callback(nf_->get_handle()); });
|
return do_io([&]() -> api_error { return callback(nf_->get_handle()); });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,38 +420,48 @@ auto open_file::native_operation(
|
|||||||
i_open_file::native_operation_callback callback) -> api_error {
|
i_open_file::native_operation_callback callback) -> api_error {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
if (fsi_.directory) {
|
if (is_directory()) {
|
||||||
return api_error::invalid_operation;
|
return set_api_error(api_error::invalid_operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_recur_mutex_lock file_lock(file_mtx_);
|
|
||||||
if (stop_requested_) {
|
if (stop_requested_) {
|
||||||
return api_error::download_stopped;
|
return set_api_error(api_error::download_stopped);
|
||||||
}
|
}
|
||||||
file_lock.unlock();
|
|
||||||
|
|
||||||
const auto is_empty_file = new_file_size == 0U;
|
auto res = check_start();
|
||||||
const auto last_chunk =
|
if (res != api_error::success) {
|
||||||
is_empty_file ? std::size_t(0U)
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = adjust_cache_size(new_file_size, false);
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto is_empty_file = new_file_size == 0U;
|
||||||
|
auto last_chunk = is_empty_file
|
||||||
|
? std::size_t(0U)
|
||||||
: static_cast<std::size_t>(utils::divide_with_ceiling(
|
: static_cast<std::size_t>(utils::divide_with_ceiling(
|
||||||
new_file_size, chunk_size_)) -
|
new_file_size, get_chunk_size())) -
|
||||||
1U;
|
1U;
|
||||||
|
|
||||||
file_lock.lock();
|
unique_recur_mutex_lock rw_lock(rw_mtx_);
|
||||||
if (not is_empty_file && (last_chunk < read_state_.size())) {
|
auto read_state = get_read_state();
|
||||||
file_lock.unlock();
|
if (not is_empty_file && (last_chunk < read_state.size())) {
|
||||||
update_background_reader(0U);
|
rw_lock.unlock();
|
||||||
|
update_reader(0U);
|
||||||
|
|
||||||
download_chunk(last_chunk, false, true);
|
download_chunk(last_chunk, false, true);
|
||||||
if (get_api_error() != api_error::success) {
|
if (get_api_error() != api_error::success) {
|
||||||
return get_api_error();
|
return get_api_error();
|
||||||
}
|
}
|
||||||
file_lock.lock();
|
rw_lock.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto original_file_size = get_file_size();
|
read_state = get_read_state();
|
||||||
|
auto original_file_size = get_file_size();
|
||||||
|
|
||||||
auto res = do_io([&]() -> api_error { return callback(nf_->get_handle()); });
|
res = do_io([&]() -> api_error { return callback(nf_->get_handle()); });
|
||||||
if (res != api_error::success) {
|
if (res != api_error::success) {
|
||||||
utils::error::raise_api_path_error(function_name, get_api_path(),
|
utils::error::raise_api_path_error(function_name, get_api_path(),
|
||||||
utils::get_last_error_code(),
|
utils::get_last_error_code(),
|
||||||
@ -290,56 +470,73 @@ auto open_file::native_operation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto file_size = nf_->size().value_or(0U);
|
auto file_size = nf_->size();
|
||||||
if (file_size != new_file_size) {
|
if (not file_size.has_value()) {
|
||||||
utils::error::raise_api_path_error(
|
utils::error::raise_api_path_error(
|
||||||
function_name, get_api_path(), api_error::file_size_mismatch,
|
function_name, get_api_path(), api_error::file_size_mismatch,
|
||||||
"allocated file size mismatch|expected|" +
|
fmt::format("failed to get file size|error|{}",
|
||||||
std::to_string(new_file_size) + "|actual|" +
|
utils::get_last_error_code()));
|
||||||
std::to_string(file_size));
|
return set_api_error(api_error::error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file_size.value() != new_file_size) {
|
||||||
|
utils::error::raise_api_path_error(
|
||||||
|
function_name, get_api_path(), api_error::file_size_mismatch,
|
||||||
|
fmt::format("file size mismatch|expected|{}|actual|{}", new_file_size,
|
||||||
|
file_size.value()));
|
||||||
return set_api_error(api_error::error);
|
return set_api_error(api_error::error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_empty_file || (read_state_.size() != (last_chunk + 1U))) {
|
if (is_empty_file || (read_state.size() != (last_chunk + 1U))) {
|
||||||
read_state_.resize(is_empty_file ? 0U : last_chunk + 1U);
|
auto old_size = read_state.size();
|
||||||
|
read_state.resize(is_empty_file ? 0U : last_chunk + 1U);
|
||||||
|
|
||||||
if (not is_empty_file) {
|
if (not is_empty_file) {
|
||||||
read_state_[last_chunk] = true;
|
for (std::size_t chunk = old_size; chunk <= last_chunk; ++chunk) {
|
||||||
|
read_state.set(chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set_read_state(read_state);
|
||||||
|
|
||||||
|
set_last_chunk_size(static_cast<std::size_t>(
|
||||||
|
new_file_size <= get_chunk_size() ? new_file_size
|
||||||
|
: (new_file_size % get_chunk_size()) == 0U
|
||||||
|
? get_chunk_size()
|
||||||
|
: new_file_size % get_chunk_size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
last_chunk_size_ = static_cast<std::size_t>(
|
if (original_file_size == new_file_size) {
|
||||||
new_file_size <= chunk_size_ ? new_file_size
|
return res;
|
||||||
: (new_file_size % chunk_size_) == 0U ? chunk_size_
|
|
||||||
: new_file_size % chunk_size_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (original_file_size != new_file_size) {
|
|
||||||
set_modified();
|
set_modified();
|
||||||
|
|
||||||
fsi_.size = new_file_size;
|
set_file_size(new_file_size);
|
||||||
const auto now = std::to_string(utils::time::get_time_now());
|
auto now = std::to_string(utils::time::get_time_now());
|
||||||
res = provider_.set_item_meta(
|
res = get_provider().set_item_meta(
|
||||||
fsi_.api_path, {
|
get_api_path(), {
|
||||||
{META_CHANGED, now},
|
{META_CHANGED, now},
|
||||||
{META_MODIFIED, now},
|
{META_MODIFIED, now},
|
||||||
{META_SIZE, std::to_string(new_file_size)},
|
{META_SIZE, std::to_string(new_file_size)},
|
||||||
{META_WRITTEN, now},
|
{META_WRITTEN, now},
|
||||||
});
|
});
|
||||||
if (res != api_error::success) {
|
if (res == api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
utils::error::raise_api_path_error(function_name, get_api_path(), res,
|
utils::error::raise_api_path_error(function_name, get_api_path(), res,
|
||||||
"failed to set file meta");
|
"failed to set file meta");
|
||||||
return set_api_error(res);
|
return set_api_error(res);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto open_file::read(std::size_t read_size, std::uint64_t read_offset,
|
auto open_file::read(std::size_t read_size, std::uint64_t read_offset,
|
||||||
data_buffer &data) -> api_error {
|
data_buffer &data) -> api_error {
|
||||||
if (fsi_.directory) {
|
if (is_directory()) {
|
||||||
return api_error::invalid_operation;
|
return set_api_error(api_error::invalid_operation);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stop_requested_) {
|
||||||
|
return set_api_error(api_error::download_stopped);
|
||||||
}
|
}
|
||||||
|
|
||||||
read_size =
|
read_size =
|
||||||
@ -348,12 +545,17 @@ auto open_file::read(std::size_t read_size, std::uint64_t read_offset,
|
|||||||
return api_error::success;
|
return api_error::success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto res = check_start();
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
const auto read_from_source = [this, &data, &read_offset,
|
const auto read_from_source = [this, &data, &read_offset,
|
||||||
&read_size]() -> api_error {
|
&read_size]() -> api_error {
|
||||||
return do_io([this, &data, &read_offset, &read_size]() -> api_error {
|
return do_io([this, &data, &read_offset, &read_size]() -> api_error {
|
||||||
if (provider_.is_direct_only()) {
|
if (get_provider().is_read_only()) {
|
||||||
return provider_.read_file_bytes(fsi_.api_path, read_size, read_offset,
|
return get_provider().read_file_bytes(
|
||||||
data, stop_requested_);
|
get_api_path(), read_size, read_offset, data, stop_requested_);
|
||||||
}
|
}
|
||||||
|
|
||||||
data.resize(read_size);
|
data.resize(read_size);
|
||||||
@ -364,47 +566,61 @@ auto open_file::read(std::size_t read_size, std::uint64_t read_offset,
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
unique_recur_mutex_lock file_lock(file_mtx_);
|
if (get_read_state().all()) {
|
||||||
if (read_state_.all()) {
|
|
||||||
reset_timeout();
|
reset_timeout();
|
||||||
return read_from_source();
|
return read_from_source();
|
||||||
}
|
}
|
||||||
file_lock.unlock();
|
|
||||||
|
|
||||||
const auto start_chunk_index =
|
auto begin_chunk = static_cast<std::size_t>(read_offset / get_chunk_size());
|
||||||
static_cast<std::size_t>(read_offset / chunk_size_);
|
auto end_chunk =
|
||||||
const auto end_chunk_index =
|
static_cast<std::size_t>((read_size + read_offset) / get_chunk_size());
|
||||||
static_cast<std::size_t>((read_size + read_offset) / chunk_size_);
|
|
||||||
|
|
||||||
update_background_reader(start_chunk_index);
|
update_reader(begin_chunk);
|
||||||
|
|
||||||
download_range(start_chunk_index, end_chunk_index, true);
|
download_range(begin_chunk, end_chunk, true);
|
||||||
if (get_api_error() != api_error::success) {
|
if (get_api_error() != api_error::success) {
|
||||||
return get_api_error();
|
return get_api_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
file_lock.lock();
|
unique_recur_mutex_lock rw_lock(rw_mtx_);
|
||||||
return get_api_error() == api_error::success ? read_from_source()
|
return get_api_error() == api_error::success ? read_from_source()
|
||||||
: get_api_error();
|
: get_api_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
void open_file::remove(std::uint64_t handle) {
|
void open_file::remove(std::uint64_t handle) {
|
||||||
recur_mutex_lock file_lock(file_mtx_);
|
|
||||||
open_file_base::remove(handle);
|
open_file_base::remove(handle);
|
||||||
if (modified_ && read_state_.all() &&
|
|
||||||
|
recur_mutex_lock rw_lock(rw_mtx_);
|
||||||
|
if (is_modified() && get_read_state().all() &&
|
||||||
(get_api_error() == api_error::success)) {
|
(get_api_error() == api_error::success)) {
|
||||||
mgr_.queue_upload(*this);
|
mgr_.queue_upload(*this);
|
||||||
modified_ = false;
|
open_file_base::set_modified(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (removed_ && (get_open_file_count() == 0U)) {
|
if (is_removed() && (get_open_file_count() == 0U)) {
|
||||||
removed_ = false;
|
open_file_base::set_removed(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void open_file::remove_all() {
|
||||||
|
open_file_base::remove_all();
|
||||||
|
|
||||||
|
recur_mutex_lock rw_lock(rw_mtx_);
|
||||||
|
open_file_base::set_modified(false);
|
||||||
|
open_file_base::set_removed(true);
|
||||||
|
|
||||||
|
mgr_.remove_upload(get_api_path());
|
||||||
|
|
||||||
|
set_api_error(api_error::success);
|
||||||
|
}
|
||||||
|
|
||||||
auto open_file::resize(std::uint64_t new_file_size) -> api_error {
|
auto open_file::resize(std::uint64_t new_file_size) -> api_error {
|
||||||
if (fsi_.directory) {
|
if (is_directory()) {
|
||||||
return api_error::invalid_operation;
|
return set_api_error(api_error::invalid_operation);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_file_size == get_file_size()) {
|
||||||
|
return api_error::success;
|
||||||
}
|
}
|
||||||
|
|
||||||
return native_operation(
|
return native_operation(
|
||||||
@ -414,115 +630,62 @@ auto open_file::resize(std::uint64_t new_file_size) -> api_error {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto open_file::close() -> bool {
|
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
|
||||||
|
|
||||||
if (not fsi_.directory && not stop_requested_) {
|
|
||||||
stop_requested_ = true;
|
|
||||||
|
|
||||||
unique_mutex_lock reader_lock(io_thread_mtx_);
|
|
||||||
io_thread_notify_.notify_all();
|
|
||||||
reader_lock.unlock();
|
|
||||||
|
|
||||||
if (reader_thread_) {
|
|
||||||
reader_thread_->join();
|
|
||||||
reader_thread_.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (open_file_base::close()) {
|
|
||||||
{
|
|
||||||
const auto err = get_api_error();
|
|
||||||
if (err == api_error::success ||
|
|
||||||
err == api_error::download_incomplete ||
|
|
||||||
err == api_error::download_stopped) {
|
|
||||||
if (modified_ && not read_state_.all()) {
|
|
||||||
set_api_error(api_error::download_incomplete);
|
|
||||||
} else if (not modified_ && (fsi_.size > 0U) &&
|
|
||||||
not read_state_.all()) {
|
|
||||||
set_api_error(api_error::download_stopped);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nf_->close();
|
|
||||||
|
|
||||||
if (modified_ && (get_api_error() == api_error::success)) {
|
|
||||||
mgr_.queue_upload(*this);
|
|
||||||
} else if (modified_ &&
|
|
||||||
(get_api_error() == api_error::download_incomplete)) {
|
|
||||||
mgr_.store_resume(*this);
|
|
||||||
} else if (get_api_error() != api_error::success) {
|
|
||||||
mgr_.remove_resume(get_api_path(), get_source_path());
|
|
||||||
if (not utils::file::file(fsi_.source_path).remove()) {
|
|
||||||
utils::error::raise_api_path_error(
|
|
||||||
function_name, get_api_path(), fsi_.source_path,
|
|
||||||
utils::get_last_error_code(), "failed to delete file");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto parent = utils::path::get_parent_path(fsi_.source_path);
|
|
||||||
fsi_.source_path =
|
|
||||||
utils::path::combine(parent, {utils::create_uuid_string()});
|
|
||||||
const auto res = provider_.set_item_meta(fsi_.api_path, META_SOURCE,
|
|
||||||
fsi_.source_path);
|
|
||||||
if (res != api_error::success) {
|
|
||||||
utils::error::raise_api_path_error(function_name, get_api_path(),
|
|
||||||
fsi_.source_path, res,
|
|
||||||
"failed to set file meta");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void open_file::set_modified() {
|
void open_file::set_modified() {
|
||||||
if (not modified_) {
|
if (not is_modified()) {
|
||||||
modified_ = true;
|
open_file_base::set_modified(true);
|
||||||
mgr_.store_resume(*this);
|
mgr_.store_resume(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not removed_) {
|
if (not is_removed()) {
|
||||||
removed_ = true;
|
open_file_base::set_removed(true);
|
||||||
mgr_.remove_upload(get_api_path());
|
mgr_.remove_upload(get_api_path());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void open_file::update_background_reader(std::size_t read_chunk) {
|
void open_file::set_read_state(std::size_t chunk) {
|
||||||
recur_mutex_lock reader_lock(file_mtx_);
|
recur_mutex_lock file_lock(get_mutex());
|
||||||
read_chunk_index_ = read_chunk;
|
read_state_.set(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
if (not reader_thread_ && not stop_requested_) {
|
void open_file::set_read_state(boost::dynamic_bitset<> read_state) {
|
||||||
reader_thread_ = std::make_unique<std::thread>([this]() {
|
recur_mutex_lock file_lock(get_mutex());
|
||||||
std::size_t next_chunk{};
|
read_state_ = std::move(read_state);
|
||||||
while (not stop_requested_) {
|
}
|
||||||
unique_recur_mutex_lock file_lock(file_mtx_);
|
|
||||||
if ((fsi_.size == 0U) || read_state_.all()) {
|
|
||||||
file_lock.unlock();
|
|
||||||
|
|
||||||
unique_mutex_lock io_lock(io_thread_mtx_);
|
void open_file::update_reader(std::size_t chunk) {
|
||||||
if (not stop_requested_ && io_thread_queue_.empty()) {
|
recur_mutex_lock rw_lock(rw_mtx_);
|
||||||
io_thread_notify_.wait(io_lock);
|
read_chunk_ = chunk;
|
||||||
|
|
||||||
|
if (reader_thread_ || stop_requested_) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
io_thread_notify_.notify_all();
|
|
||||||
io_lock.unlock();
|
|
||||||
} else {
|
|
||||||
do {
|
|
||||||
next_chunk = read_chunk_index_ =
|
|
||||||
((read_chunk_index_ + 1U) >= read_state_.size())
|
|
||||||
? 0U
|
|
||||||
: read_chunk_index_ + 1U;
|
|
||||||
} while ((next_chunk != 0U) && (active_downloads_.find(next_chunk) !=
|
|
||||||
active_downloads_.end()));
|
|
||||||
|
|
||||||
file_lock.unlock();
|
reader_thread_ = std::make_unique<std::thread>([this]() {
|
||||||
|
unique_recur_mutex_lock lock(rw_mtx_);
|
||||||
|
auto next_chunk{read_chunk_};
|
||||||
|
auto read_chunk{read_chunk_};
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
|
while (not 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_);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read_chunk != read_chunk_) {
|
||||||
|
next_chunk = read_chunk = read_chunk_;
|
||||||
|
}
|
||||||
|
|
||||||
|
next_chunk = next_chunk + 1U >= read_state.size() ? 0U : next_chunk + 1U;
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
download_chunk(next_chunk, true, false);
|
download_chunk(next_chunk, true, false);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto open_file::write(std::uint64_t write_offset, const data_buffer &data,
|
auto open_file::write(std::uint64_t write_offset, const data_buffer &data,
|
||||||
@ -531,42 +694,44 @@ auto open_file::write(std::uint64_t write_offset, const data_buffer &data,
|
|||||||
|
|
||||||
bytes_written = 0U;
|
bytes_written = 0U;
|
||||||
|
|
||||||
if (fsi_.directory || provider_.is_direct_only()) {
|
if (is_directory() || get_provider().is_read_only()) {
|
||||||
return api_error::invalid_operation;
|
return set_api_error(api_error::invalid_operation);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.empty()) {
|
if (data.empty()) {
|
||||||
return api_error::success;
|
return api_error::success;
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_recur_mutex_lock write_lock(file_mtx_);
|
|
||||||
if (stop_requested_) {
|
if (stop_requested_) {
|
||||||
return api_error::download_stopped;
|
return set_api_error(api_error::download_stopped);
|
||||||
}
|
}
|
||||||
write_lock.unlock();
|
|
||||||
|
|
||||||
const auto start_chunk_index =
|
auto res = check_start();
|
||||||
static_cast<std::size_t>(write_offset / chunk_size_);
|
if (res != api_error::success) {
|
||||||
const auto end_chunk_index =
|
return res;
|
||||||
static_cast<std::size_t>((write_offset + data.size()) / chunk_size_);
|
}
|
||||||
|
|
||||||
update_background_reader(start_chunk_index);
|
auto begin_chunk = static_cast<std::size_t>(write_offset / get_chunk_size());
|
||||||
|
auto end_chunk =
|
||||||
|
static_cast<std::size_t>((write_offset + data.size()) / get_chunk_size());
|
||||||
|
|
||||||
download_range(start_chunk_index,
|
update_reader(begin_chunk);
|
||||||
std::min(read_state_.size() - 1U, end_chunk_index), true);
|
|
||||||
|
download_range(begin_chunk, std::min(get_read_state().size() - 1U, end_chunk),
|
||||||
|
true);
|
||||||
if (get_api_error() != api_error::success) {
|
if (get_api_error() != api_error::success) {
|
||||||
return get_api_error();
|
return get_api_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
write_lock.lock();
|
unique_recur_mutex_lock rw_lock(rw_mtx_);
|
||||||
if ((write_offset + data.size()) > fsi_.size) {
|
if ((write_offset + data.size()) > get_file_size()) {
|
||||||
auto res = resize(write_offset + data.size());
|
res = resize(write_offset + data.size());
|
||||||
if (res != api_error::success) {
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto res = do_io([&]() -> api_error {
|
res = do_io([&]() -> api_error {
|
||||||
if (not nf_->write(data, write_offset, &bytes_written)) {
|
if (not nf_->write(data, write_offset, &bytes_written)) {
|
||||||
return api_error::os_error;
|
return api_error::os_error;
|
||||||
}
|
}
|
||||||
@ -578,8 +743,8 @@ auto open_file::write(std::uint64_t write_offset, const data_buffer &data,
|
|||||||
return set_api_error(res);
|
return set_api_error(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto now = std::to_string(utils::time::get_time_now());
|
auto now = std::to_string(utils::time::get_time_now());
|
||||||
res = provider_.set_item_meta(fsi_.api_path, {
|
res = get_provider().set_item_meta(get_api_path(), {
|
||||||
{META_CHANGED, now},
|
{META_CHANGED, now},
|
||||||
{META_MODIFIED, now},
|
{META_MODIFIED, now},
|
||||||
{META_WRITTEN, now},
|
{META_WRITTEN, now},
|
||||||
|
@ -35,13 +35,15 @@ void open_file_base::download::notify(const api_error &err) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto open_file_base::download::wait() -> api_error {
|
auto open_file_base::download::wait() -> api_error {
|
||||||
if (not complete_) {
|
if (complete_) {
|
||||||
|
return error_;
|
||||||
|
}
|
||||||
|
|
||||||
unique_mutex_lock lock(mtx_);
|
unique_mutex_lock lock(mtx_);
|
||||||
if (not complete_) {
|
if (not complete_) {
|
||||||
notify_.wait(lock);
|
notify_.wait(lock);
|
||||||
}
|
}
|
||||||
notify_.notify_all();
|
notify_.notify_all();
|
||||||
}
|
|
||||||
|
|
||||||
return error_;
|
return error_;
|
||||||
}
|
}
|
||||||
@ -65,12 +67,14 @@ auto open_file_base::io_item::get_result() -> api_error {
|
|||||||
|
|
||||||
open_file_base::open_file_base(std::uint64_t chunk_size,
|
open_file_base::open_file_base(std::uint64_t chunk_size,
|
||||||
std::uint8_t chunk_timeout, filesystem_item fsi,
|
std::uint8_t chunk_timeout, filesystem_item fsi,
|
||||||
i_provider &provider)
|
i_provider &provider, bool disable_io)
|
||||||
: open_file_base(chunk_size, chunk_timeout, fsi, {}, provider) {}
|
: open_file_base(chunk_size, chunk_timeout, fsi, {}, provider, disable_io) {
|
||||||
|
}
|
||||||
|
|
||||||
open_file_base::open_file_base(
|
open_file_base::open_file_base(
|
||||||
std::uint64_t chunk_size, std::uint8_t chunk_timeout, filesystem_item fsi,
|
std::uint64_t chunk_size, std::uint8_t chunk_timeout, filesystem_item fsi,
|
||||||
std::map<std::uint64_t, open_file_data> open_data, i_provider &provider)
|
std::map<std::uint64_t, open_file_data> open_data, i_provider &provider,
|
||||||
|
bool disable_io)
|
||||||
: chunk_size_(chunk_size),
|
: chunk_size_(chunk_size),
|
||||||
chunk_timeout_(chunk_timeout),
|
chunk_timeout_(chunk_timeout),
|
||||||
fsi_(std::move(fsi)),
|
fsi_(std::move(fsi)),
|
||||||
@ -80,7 +84,7 @@ open_file_base::open_file_base(
|
|||||||
: fsi.size % chunk_size)),
|
: fsi.size % chunk_size)),
|
||||||
open_data_(std::move(open_data)),
|
open_data_(std::move(open_data)),
|
||||||
provider_(provider) {
|
provider_(provider) {
|
||||||
if (not fsi.directory) {
|
if (not fsi.directory && not disable_io) {
|
||||||
io_thread_ = std::make_unique<std::thread>([this] { file_io_thread(); });
|
io_thread_ = std::make_unique<std::thread>([this] { file_io_thread(); });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -115,20 +119,38 @@ auto open_file_base::can_close() const -> bool {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_download_complete()) {
|
if (is_complete()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (provider_.is_direct_only()) {
|
if (provider_.is_read_only()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::chrono::system_clock::time_point last_access = last_access_;
|
std::chrono::system_clock::time_point last_access{last_access_};
|
||||||
const auto duration = std::chrono::duration_cast<std::chrono::seconds>(
|
auto duration = std::chrono::duration_cast<std::chrono::seconds>(
|
||||||
std::chrono::system_clock::now() - last_access);
|
std::chrono::system_clock::now() - last_access);
|
||||||
return (duration.count() >= chunk_timeout_);
|
return (duration.count() >= chunk_timeout_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto open_file_base::close() -> bool {
|
||||||
|
unique_mutex_lock io_lock(io_thread_mtx_);
|
||||||
|
if (io_stop_requested_ || not io_thread_) {
|
||||||
|
io_thread_notify_.notify_all();
|
||||||
|
io_lock.unlock();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
io_stop_requested_ = true;
|
||||||
|
io_thread_notify_.notify_all();
|
||||||
|
io_lock.unlock();
|
||||||
|
|
||||||
|
io_thread_->join();
|
||||||
|
io_thread_.reset();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
auto open_file_base::do_io(std::function<api_error()> action) -> api_error {
|
auto open_file_base::do_io(std::function<api_error()> action) -> api_error {
|
||||||
unique_mutex_lock io_lock(io_thread_mtx_);
|
unique_mutex_lock io_lock(io_thread_mtx_);
|
||||||
auto item = std::make_shared<io_item>(action);
|
auto item = std::make_shared<io_item>(action);
|
||||||
@ -187,6 +209,36 @@ auto open_file_base::get_file_size() const -> std::uint64_t {
|
|||||||
return fsi_.size;
|
return fsi_.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] auto open_file_base::get_last_chunk_size() const -> std::size_t {
|
||||||
|
recur_mutex_lock file_lock(file_mtx_);
|
||||||
|
return last_chunk_size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void open_file_base::set_file_size(std::uint64_t size) {
|
||||||
|
recur_mutex_lock file_lock(file_mtx_);
|
||||||
|
fsi_.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void open_file_base::set_last_chunk_size(std::size_t size) {
|
||||||
|
recur_mutex_lock file_lock(file_mtx_);
|
||||||
|
last_chunk_size_ = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void open_file_base::set_modified(bool modified) {
|
||||||
|
recur_mutex_lock file_lock(file_mtx_);
|
||||||
|
modified_ = modified;
|
||||||
|
}
|
||||||
|
|
||||||
|
void open_file_base::set_removed(bool removed) {
|
||||||
|
recur_mutex_lock file_lock(file_mtx_);
|
||||||
|
removed_ = removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void open_file_base::set_source_path(std::string source_path) {
|
||||||
|
recur_mutex_lock file_lock(file_mtx_);
|
||||||
|
fsi_.source_path = std::move(source_path);
|
||||||
|
}
|
||||||
|
|
||||||
auto open_file_base::get_filesystem_item() const -> filesystem_item {
|
auto open_file_base::get_filesystem_item() const -> filesystem_item {
|
||||||
recur_mutex_lock file_lock(file_mtx_);
|
recur_mutex_lock file_lock(file_mtx_);
|
||||||
return fsi_;
|
return fsi_;
|
||||||
@ -194,8 +246,9 @@ auto open_file_base::get_filesystem_item() const -> filesystem_item {
|
|||||||
|
|
||||||
auto open_file_base::get_handles() const -> std::vector<std::uint64_t> {
|
auto open_file_base::get_handles() const -> std::vector<std::uint64_t> {
|
||||||
recur_mutex_lock file_lock(file_mtx_);
|
recur_mutex_lock file_lock(file_mtx_);
|
||||||
|
|
||||||
std::vector<std::uint64_t> ret;
|
std::vector<std::uint64_t> ret;
|
||||||
for (auto &&item : open_data_) {
|
for (const auto &item : open_data_) {
|
||||||
ret.emplace_back(item.first);
|
ret.emplace_back(item.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,20 +283,64 @@ auto open_file_base::get_open_file_count() const -> std::size_t {
|
|||||||
return open_data_.size();
|
return open_data_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto open_file_base::get_source_path() const -> std::string {
|
||||||
|
recur_mutex_lock file_lock(file_mtx_);
|
||||||
|
return fsi_.source_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto open_file_base::has_handle(std::uint64_t handle) const -> bool {
|
||||||
|
recur_mutex_lock file_lock(file_mtx_);
|
||||||
|
return open_data_.find(handle) != open_data_.end();
|
||||||
|
}
|
||||||
|
|
||||||
auto open_file_base::is_modified() const -> bool {
|
auto open_file_base::is_modified() const -> bool {
|
||||||
recur_mutex_lock file_lock(file_mtx_);
|
recur_mutex_lock file_lock(file_mtx_);
|
||||||
return modified_;
|
return modified_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto open_file_base::is_removed() const -> bool {
|
||||||
|
recur_mutex_lock file_lock(file_mtx_);
|
||||||
|
return removed_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void open_file_base::notify_io() {
|
||||||
|
mutex_lock io_lock(io_thread_mtx_);
|
||||||
|
io_thread_notify_.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
void open_file_base::remove(std::uint64_t handle) {
|
void open_file_base::remove(std::uint64_t handle) {
|
||||||
recur_mutex_lock file_lock(file_mtx_);
|
recur_mutex_lock file_lock(file_mtx_);
|
||||||
|
if (open_data_.find(handle) == open_data_.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
open_data_.erase(handle);
|
open_data_.erase(handle);
|
||||||
event_system::instance().raise<filesystem_item_handle_closed>(
|
event_system::instance().raise<filesystem_item_handle_closed>(
|
||||||
fsi_.api_path, handle, fsi_.source_path, fsi_.directory, modified_);
|
fsi_.api_path, handle, fsi_.source_path, fsi_.directory, modified_);
|
||||||
if (open_data_.empty()) {
|
if (not open_data_.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
event_system::instance().raise<filesystem_item_closed>(
|
event_system::instance().raise<filesystem_item_closed>(
|
||||||
fsi_.api_path, fsi_.source_path, fsi_.directory, modified_);
|
fsi_.api_path, fsi_.source_path, fsi_.directory, modified_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void open_file_base::remove_all() {
|
||||||
|
recur_mutex_lock file_lock(file_mtx_);
|
||||||
|
if (open_data_.empty()) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto open_data = open_data_;
|
||||||
|
open_data_.clear();
|
||||||
|
|
||||||
|
for (const auto &data : open_data) {
|
||||||
|
event_system::instance().raise<filesystem_item_handle_closed>(
|
||||||
|
fsi_.api_path, data.first, fsi_.source_path, fsi_.directory, modified_);
|
||||||
|
}
|
||||||
|
|
||||||
|
event_system::instance().raise<filesystem_item_closed>(
|
||||||
|
fsi_.api_path, fsi_.source_path, fsi_.directory, modified_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void open_file_base::reset_timeout() {
|
void open_file_base::reset_timeout() {
|
||||||
@ -252,15 +349,15 @@ void open_file_base::reset_timeout() {
|
|||||||
|
|
||||||
auto open_file_base::set_api_error(const api_error &err) -> api_error {
|
auto open_file_base::set_api_error(const api_error &err) -> api_error {
|
||||||
mutex_lock error_lock(error_mtx_);
|
mutex_lock error_lock(error_mtx_);
|
||||||
if (error_ != err) {
|
if (error_ == err) {
|
||||||
|
return error_;
|
||||||
|
}
|
||||||
|
|
||||||
return ((error_ = (error_ == api_error::success ||
|
return ((error_ = (error_ == api_error::success ||
|
||||||
error_ == api_error::download_incomplete ||
|
error_ == api_error::download_incomplete ||
|
||||||
error_ == api_error::download_stopped
|
error_ == api_error::download_stopped
|
||||||
? err
|
? err
|
||||||
: error_)));
|
: error_)));
|
||||||
}
|
|
||||||
|
|
||||||
return error_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void open_file_base::set_api_path(const std::string &api_path) {
|
void open_file_base::set_api_path(const std::string &api_path) {
|
||||||
@ -269,24 +366,12 @@ void open_file_base::set_api_path(const std::string &api_path) {
|
|||||||
fsi_.api_parent = utils::path::get_parent_api_path(api_path);
|
fsi_.api_parent = utils::path::get_parent_api_path(api_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto open_file_base::close() -> bool {
|
void open_file_base::wait_for_io(stop_type &stop_requested) {
|
||||||
unique_mutex_lock io_lock(io_thread_mtx_);
|
unique_mutex_lock io_lock(io_thread_mtx_);
|
||||||
if (not fsi_.directory && not io_stop_requested_) {
|
if (not stop_requested && io_thread_queue_.empty()) {
|
||||||
io_stop_requested_ = true;
|
io_thread_notify_.wait(io_lock);
|
||||||
|
}
|
||||||
io_thread_notify_.notify_all();
|
io_thread_notify_.notify_all();
|
||||||
io_lock.unlock();
|
io_lock.unlock();
|
||||||
|
|
||||||
if (io_thread_) {
|
|
||||||
io_thread_->join();
|
|
||||||
io_thread_.reset();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
io_thread_notify_.notify_all();
|
|
||||||
io_lock.unlock();
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
367
repertory/librepertory/src/file_manager/ring_buffer_base.cpp
Normal file
367
repertory/librepertory/src/file_manager/ring_buffer_base.cpp
Normal file
@ -0,0 +1,367 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
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 "file_manager/ring_buffer_base.hpp"
|
||||||
|
|
||||||
|
#include "events/event_system.hpp"
|
||||||
|
#include "file_manager/events.hpp"
|
||||||
|
#include "file_manager/open_file_base.hpp"
|
||||||
|
#include "platform/platform.hpp"
|
||||||
|
#include "providers/i_provider.hpp"
|
||||||
|
#include "types/repertory.hpp"
|
||||||
|
#include "utils/common.hpp"
|
||||||
|
#include "utils/error_utils.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
ring_buffer_base::ring_buffer_base(std::uint64_t chunk_size,
|
||||||
|
std::uint8_t chunk_timeout,
|
||||||
|
filesystem_item fsi, i_provider &provider,
|
||||||
|
std::size_t ring_size, bool disable_io)
|
||||||
|
: open_file_base(chunk_size, chunk_timeout, fsi, provider, disable_io),
|
||||||
|
read_state_(ring_size),
|
||||||
|
total_chunks_(static_cast<std::size_t>(
|
||||||
|
utils::divide_with_ceiling(fsi.size, chunk_size))) {
|
||||||
|
if (disable_io) {
|
||||||
|
if (fsi.size > 0U) {
|
||||||
|
read_state_.resize(std::min(total_chunks_, read_state_.size()));
|
||||||
|
|
||||||
|
ring_end_ =
|
||||||
|
std::min(total_chunks_ - 1U, ring_begin_ + read_state_.size() - 1U);
|
||||||
|
read_state_.set(0U, read_state_.size(), false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ring_size < min_ring_size) {
|
||||||
|
throw std::runtime_error("ring size must be greater than or equal to 5");
|
||||||
|
}
|
||||||
|
|
||||||
|
ring_end_ = std::min(total_chunks_ - 1U, ring_begin_ + ring_size - 1U);
|
||||||
|
read_state_.set(0U, ring_size, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ring_buffer_base::check_start() -> api_error {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (on_check_start()) {
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
event_system::instance().raise<download_begin>(get_api_path(),
|
||||||
|
get_source_path());
|
||||||
|
reader_thread_ =
|
||||||
|
std::make_unique<std::thread>([this]() { reader_thread(); });
|
||||||
|
return api_error::success;
|
||||||
|
} catch (const std::exception &ex) {
|
||||||
|
utils::error::raise_api_path_error(function_name, get_api_path(),
|
||||||
|
get_source_path(), ex,
|
||||||
|
"failed to start");
|
||||||
|
return api_error::error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ring_buffer_base::close() -> bool {
|
||||||
|
stop_requested_ = true;
|
||||||
|
|
||||||
|
unique_mutex_lock chunk_lock(chunk_mtx_);
|
||||||
|
chunk_notify_.notify_all();
|
||||||
|
chunk_lock.unlock();
|
||||||
|
|
||||||
|
auto res = open_file_base::close();
|
||||||
|
|
||||||
|
if (reader_thread_) {
|
||||||
|
reader_thread_->join();
|
||||||
|
reader_thread_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ring_buffer_base::download_chunk(std::size_t chunk,
|
||||||
|
bool skip_active) -> api_error {
|
||||||
|
unique_mutex_lock chunk_lock(chunk_mtx_);
|
||||||
|
const auto unlock_and_notify = [this, &chunk_lock]() {
|
||||||
|
chunk_notify_.notify_all();
|
||||||
|
chunk_lock.unlock();
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto unlock_and_return =
|
||||||
|
[&unlock_and_notify](api_error res) -> api_error {
|
||||||
|
unlock_and_notify();
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (chunk < ring_begin_ || chunk > ring_end_) {
|
||||||
|
return unlock_and_return(api_error::invalid_ring_buffer_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_active_downloads().find(chunk) != get_active_downloads().end()) {
|
||||||
|
if (skip_active) {
|
||||||
|
return unlock_and_return(api_error::success);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto active_download = get_active_downloads().at(chunk);
|
||||||
|
unlock_and_notify();
|
||||||
|
|
||||||
|
return active_download->wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read_state_[chunk % read_state_.size()]) {
|
||||||
|
return unlock_and_return(api_error::success);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto active_download{std::make_shared<download>()};
|
||||||
|
get_active_downloads()[chunk] = active_download;
|
||||||
|
|
||||||
|
return use_buffer(chunk, [&](data_buffer &buffer) -> api_error {
|
||||||
|
auto data_offset{chunk * get_chunk_size()};
|
||||||
|
auto data_size{
|
||||||
|
chunk == (total_chunks_ - 1U) ? get_last_chunk_size()
|
||||||
|
: get_chunk_size(),
|
||||||
|
};
|
||||||
|
unlock_and_notify();
|
||||||
|
|
||||||
|
auto result{
|
||||||
|
get_provider().read_file_bytes(get_api_path(), data_size, data_offset,
|
||||||
|
buffer, stop_requested_),
|
||||||
|
};
|
||||||
|
|
||||||
|
chunk_lock.lock();
|
||||||
|
if (chunk < ring_begin_ || chunk > ring_end_) {
|
||||||
|
result = api_error::invalid_ring_buffer_position;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == api_error::success) {
|
||||||
|
result = on_chunk_downloaded(chunk, buffer);
|
||||||
|
if (result == api_error::success) {
|
||||||
|
read_state_[chunk % read_state_.size()] = true;
|
||||||
|
auto progress = (static_cast<double>(chunk + 1U) /
|
||||||
|
static_cast<double>(total_chunks_)) *
|
||||||
|
100.0;
|
||||||
|
event_system::instance().raise<download_progress>(
|
||||||
|
get_api_path(), get_source_path(), progress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get_active_downloads().erase(chunk);
|
||||||
|
unlock_and_notify();
|
||||||
|
|
||||||
|
active_download->notify(result);
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ring_buffer_base::forward(std::size_t count) {
|
||||||
|
update_position(count, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ring_buffer_base::get_read_state() const -> boost::dynamic_bitset<> {
|
||||||
|
recur_mutex_lock file_lock(get_mutex());
|
||||||
|
return read_state_;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ring_buffer_base::get_read_state(std::size_t chunk) const -> bool {
|
||||||
|
recur_mutex_lock file_lock(get_mutex());
|
||||||
|
return read_state_[chunk % read_state_.size()];
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ring_buffer_base::read(std::size_t read_size, std::uint64_t read_offset,
|
||||||
|
data_buffer &data) -> api_error {
|
||||||
|
if (is_directory()) {
|
||||||
|
return api_error::invalid_operation;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_timeout();
|
||||||
|
|
||||||
|
read_size =
|
||||||
|
utils::calculate_read_size(get_file_size(), read_size, read_offset);
|
||||||
|
if (read_size == 0U) {
|
||||||
|
return api_error::success;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto begin_chunk{static_cast<std::size_t>(read_offset / get_chunk_size())};
|
||||||
|
read_offset = read_offset - (begin_chunk * get_chunk_size());
|
||||||
|
|
||||||
|
unique_mutex_lock read_lock(read_mtx_);
|
||||||
|
auto res = check_start();
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::size_t chunk = begin_chunk;
|
||||||
|
not stop_requested_ && (res == api_error::success) && (read_size > 0U);
|
||||||
|
++chunk) {
|
||||||
|
reset_timeout();
|
||||||
|
|
||||||
|
if (chunk > ring_pos_) {
|
||||||
|
forward(chunk - ring_pos_);
|
||||||
|
} else if (chunk < ring_pos_) {
|
||||||
|
reverse(ring_pos_ - chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
res = download_chunk(chunk, false);
|
||||||
|
if (res != api_error::success) {
|
||||||
|
if (res == api_error::invalid_ring_buffer_position) {
|
||||||
|
read_lock.unlock();
|
||||||
|
|
||||||
|
// TODO limit retry
|
||||||
|
return read(read_size, read_offset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_timeout();
|
||||||
|
|
||||||
|
std::size_t bytes_read{};
|
||||||
|
res = on_read_chunk(
|
||||||
|
chunk,
|
||||||
|
std::min(static_cast<std::size_t>(get_chunk_size() - read_offset),
|
||||||
|
read_size),
|
||||||
|
read_offset, data, bytes_read);
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_timeout();
|
||||||
|
|
||||||
|
read_size -= bytes_read;
|
||||||
|
read_offset = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stop_requested_ ? api_error::download_stopped : res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ring_buffer_base::reader_thread() {
|
||||||
|
unique_mutex_lock chunk_lock(chunk_mtx_);
|
||||||
|
auto next_chunk{ring_pos_};
|
||||||
|
chunk_notify_.notify_all();
|
||||||
|
chunk_lock.unlock();
|
||||||
|
|
||||||
|
while (not 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_) {
|
||||||
|
chunk_notify_.notify_all();
|
||||||
|
chunk_lock.unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_read_state().all()) {
|
||||||
|
chunk_notify_.wait(chunk_lock);
|
||||||
|
next_chunk = ring_pos_;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk_notify_.notify_all();
|
||||||
|
chunk_lock.unlock();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (read_state_[next_chunk % read_state_.size()]) {
|
||||||
|
check_and_wait();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk_notify_.notify_all();
|
||||||
|
chunk_lock.unlock();
|
||||||
|
|
||||||
|
download_chunk(next_chunk, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
event_system::instance().raise<download_end>(
|
||||||
|
get_api_path(), get_source_path(), api_error::download_stopped);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ring_buffer_base::reverse(std::size_t count) {
|
||||||
|
update_position(count, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ring_buffer_base::set(std::size_t first_chunk, std::size_t current_chunk) {
|
||||||
|
mutex_lock chunk_lock(chunk_mtx_);
|
||||||
|
if (first_chunk >= total_chunks_) {
|
||||||
|
chunk_notify_.notify_all();
|
||||||
|
throw std::runtime_error("first chunk must be less than total chunks");
|
||||||
|
}
|
||||||
|
|
||||||
|
ring_begin_ = first_chunk;
|
||||||
|
ring_end_ =
|
||||||
|
std::min(total_chunks_ - 1U, ring_begin_ + read_state_.size() - 1U);
|
||||||
|
|
||||||
|
if (current_chunk > ring_end_) {
|
||||||
|
chunk_notify_.notify_all();
|
||||||
|
throw std::runtime_error(
|
||||||
|
"current chunk must be less than or equal to last chunk");
|
||||||
|
}
|
||||||
|
|
||||||
|
ring_pos_ = current_chunk;
|
||||||
|
read_state_.set(0U, read_state_.size(), true);
|
||||||
|
|
||||||
|
chunk_notify_.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ring_buffer_base::set_api_path(const std::string &api_path) {
|
||||||
|
mutex_lock chunk_lock(chunk_mtx_);
|
||||||
|
open_file_base::set_api_path(api_path);
|
||||||
|
chunk_notify_.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ring_buffer_base::update_position(std::size_t count, bool is_forward) {
|
||||||
|
mutex_lock chunk_lock(chunk_mtx_);
|
||||||
|
|
||||||
|
if (is_forward) {
|
||||||
|
if ((ring_pos_ + count) > (total_chunks_ - 1U)) {
|
||||||
|
count = (total_chunks_ - 1U) - ring_pos_;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
count = std::min(ring_pos_, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_forward ? (ring_pos_ + count) <= ring_end_
|
||||||
|
: (ring_pos_ - count) >= ring_begin_) {
|
||||||
|
ring_pos_ += is_forward ? count : -count;
|
||||||
|
} else {
|
||||||
|
auto delta = is_forward ? count - (ring_end_ - ring_pos_)
|
||||||
|
: count - (ring_pos_ - ring_begin_);
|
||||||
|
|
||||||
|
if (delta >= read_state_.size()) {
|
||||||
|
read_state_.set(0U, read_state_.size(), false);
|
||||||
|
ring_pos_ += is_forward ? count : -count;
|
||||||
|
ring_begin_ += is_forward ? delta : -delta;
|
||||||
|
} else {
|
||||||
|
for (std::size_t idx = 0U; idx < delta; ++idx) {
|
||||||
|
if (is_forward) {
|
||||||
|
read_state_[(ring_begin_ + idx) % read_state_.size()] = false;
|
||||||
|
} else {
|
||||||
|
read_state_[(ring_end_ - idx) % read_state_.size()] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ring_begin_ += is_forward ? delta : -delta;
|
||||||
|
ring_pos_ += is_forward ? count : -count;
|
||||||
|
}
|
||||||
|
|
||||||
|
ring_end_ =
|
||||||
|
std::min(total_chunks_ - 1U, ring_begin_ + read_state_.size() - 1U);
|
||||||
|
}
|
||||||
|
|
||||||
|
chunk_notify_.notify_all();
|
||||||
|
}
|
||||||
|
} // namespace repertory
|
@ -21,73 +21,30 @@
|
|||||||
*/
|
*/
|
||||||
#include "file_manager/ring_buffer_open_file.hpp"
|
#include "file_manager/ring_buffer_open_file.hpp"
|
||||||
|
|
||||||
#include "app_config.hpp"
|
|
||||||
#include "file_manager/events.hpp"
|
|
||||||
#include "file_manager/open_file_base.hpp"
|
#include "file_manager/open_file_base.hpp"
|
||||||
#include "platform/platform.hpp"
|
#include "platform/platform.hpp"
|
||||||
#include "providers/i_provider.hpp"
|
#include "providers/i_provider.hpp"
|
||||||
#include "types/repertory.hpp"
|
#include "types/repertory.hpp"
|
||||||
#include "utils/common.hpp"
|
#include "utils/common.hpp"
|
||||||
#include "utils/encrypting_reader.hpp"
|
#include "utils/error_utils.hpp"
|
||||||
#include "utils/file_utils.hpp"
|
|
||||||
#include "utils/path.hpp"
|
#include "utils/path.hpp"
|
||||||
#include "utils/utils.hpp"
|
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
ring_buffer_open_file::ring_buffer_open_file(std::string buffer_directory,
|
|
||||||
std::uint64_t chunk_size,
|
|
||||||
std::uint8_t chunk_timeout,
|
|
||||||
filesystem_item fsi,
|
|
||||||
i_provider &provider)
|
|
||||||
: ring_buffer_open_file(std::move(buffer_directory), chunk_size,
|
|
||||||
chunk_timeout, std::move(fsi), provider,
|
|
||||||
(1024ULL * 1024ULL * 1024ULL) / chunk_size) {}
|
|
||||||
|
|
||||||
ring_buffer_open_file::ring_buffer_open_file(std::string buffer_directory,
|
ring_buffer_open_file::ring_buffer_open_file(std::string buffer_directory,
|
||||||
std::uint64_t chunk_size,
|
std::uint64_t chunk_size,
|
||||||
std::uint8_t chunk_timeout,
|
std::uint8_t chunk_timeout,
|
||||||
filesystem_item fsi,
|
filesystem_item fsi,
|
||||||
i_provider &provider,
|
i_provider &provider,
|
||||||
std::size_t ring_size)
|
std::size_t ring_size)
|
||||||
: open_file_base(chunk_size, chunk_timeout, fsi, provider),
|
: ring_buffer_base(chunk_size, chunk_timeout, fsi, provider, ring_size,
|
||||||
ring_state_(ring_size),
|
false),
|
||||||
total_chunks_(static_cast<std::size_t>(
|
source_path_(utils::path::combine(buffer_directory,
|
||||||
utils::divide_with_ceiling(fsi.size, chunk_size_))) {
|
{
|
||||||
if ((ring_size % 2U) != 0U) {
|
utils::create_uuid_string(),
|
||||||
throw std::runtime_error("ring size must be a multiple of 2");
|
})) {
|
||||||
}
|
if (not can_handle_file(fsi.size, chunk_size, ring_size)) {
|
||||||
|
|
||||||
if (ring_size < 4U) {
|
|
||||||
throw std::runtime_error("ring size must be greater than or equal to 4");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fsi.size < (ring_state_.size() * chunk_size)) {
|
|
||||||
throw std::runtime_error("file size is less than ring buffer size");
|
throw std::runtime_error("file size is less than ring buffer size");
|
||||||
}
|
}
|
||||||
|
|
||||||
last_chunk_ = ring_state_.size() - 1U;
|
|
||||||
ring_state_.set(0U, ring_state_.size(), true);
|
|
||||||
|
|
||||||
buffer_directory = utils::path::absolute(buffer_directory);
|
|
||||||
if (not utils::file::directory(buffer_directory).create_directory()) {
|
|
||||||
throw std::runtime_error("failed to create buffer directory|path|" +
|
|
||||||
buffer_directory + "|err|" +
|
|
||||||
std::to_string(utils::get_last_error_code()));
|
|
||||||
}
|
|
||||||
|
|
||||||
fsi_.source_path =
|
|
||||||
utils::path::combine(buffer_directory, {utils::create_uuid_string()});
|
|
||||||
nf_ = utils::file::file::open_or_create_file(fsi_.source_path);
|
|
||||||
if (not*nf_) {
|
|
||||||
throw std::runtime_error("failed to create buffer file|err|" +
|
|
||||||
std::to_string(utils::get_last_error_code()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (not nf_->truncate(ring_state_.size() * chunk_size)) {
|
|
||||||
nf_->close();
|
|
||||||
throw std::runtime_error("failed to resize buffer file|err|" +
|
|
||||||
std::to_string(utils::get_last_error_code()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ring_buffer_open_file::~ring_buffer_open_file() {
|
ring_buffer_open_file::~ring_buffer_open_file() {
|
||||||
@ -95,107 +52,24 @@ ring_buffer_open_file::~ring_buffer_open_file() {
|
|||||||
|
|
||||||
close();
|
close();
|
||||||
|
|
||||||
|
if (not nf_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
nf_->close();
|
nf_->close();
|
||||||
if (not utils::file::file(fsi_.source_path).remove()) {
|
nf_.reset();
|
||||||
|
|
||||||
|
if (not utils::file::file(source_path_).remove()) {
|
||||||
utils::error::raise_api_path_error(
|
utils::error::raise_api_path_error(
|
||||||
function_name, fsi_.api_path, fsi_.source_path,
|
function_name, get_api_path(), source_path_,
|
||||||
utils::get_last_error_code(), "failed to delete file");
|
utils::get_last_error_code(), "failed to delete file");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ring_buffer_open_file::download_chunk(std::size_t chunk) -> api_error {
|
auto ring_buffer_open_file::can_handle_file(std::uint64_t file_size,
|
||||||
unique_mutex_lock chunk_lock(chunk_mtx_);
|
std::size_t chunk_size,
|
||||||
if (active_downloads_.find(chunk) != active_downloads_.end()) {
|
std::size_t ring_size) -> bool {
|
||||||
auto active_download = active_downloads_.at(chunk);
|
return file_size >= (static_cast<std::uint64_t>(ring_size) * chunk_size);
|
||||||
chunk_notify_.notify_all();
|
|
||||||
chunk_lock.unlock();
|
|
||||||
|
|
||||||
return active_download->wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ring_state_[chunk % ring_state_.size()]) {
|
|
||||||
auto active_download = std::make_shared<download>();
|
|
||||||
active_downloads_[chunk] = active_download;
|
|
||||||
ring_state_[chunk % ring_state_.size()] = false;
|
|
||||||
chunk_notify_.notify_all();
|
|
||||||
chunk_lock.unlock();
|
|
||||||
|
|
||||||
data_buffer buffer((chunk == (total_chunks_ - 1U)) ? last_chunk_size_
|
|
||||||
: chunk_size_);
|
|
||||||
|
|
||||||
stop_type stop_requested = !!ring_state_[chunk % ring_state_.size()];
|
|
||||||
auto res =
|
|
||||||
provider_.read_file_bytes(fsi_.api_path, buffer.size(),
|
|
||||||
chunk * chunk_size_, buffer, stop_requested);
|
|
||||||
if (res == api_error::success) {
|
|
||||||
res = do_io([&]() -> api_error {
|
|
||||||
std::size_t bytes_written{};
|
|
||||||
if (not nf_->write(buffer, (chunk % ring_state_.size()) * chunk_size_,
|
|
||||||
&bytes_written)) {
|
|
||||||
return api_error::os_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return api_error::success;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
active_download->notify(res);
|
|
||||||
|
|
||||||
chunk_lock.lock();
|
|
||||||
active_downloads_.erase(chunk);
|
|
||||||
chunk_notify_.notify_all();
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
chunk_notify_.notify_all();
|
|
||||||
chunk_lock.unlock();
|
|
||||||
|
|
||||||
return api_error::success;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ring_buffer_open_file::forward(std::size_t count) {
|
|
||||||
mutex_lock chunk_lock(chunk_mtx_);
|
|
||||||
if ((current_chunk_ + count) > (total_chunks_ - 1U)) {
|
|
||||||
count = (total_chunks_ - 1U) - current_chunk_;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((current_chunk_ + count) <= last_chunk_) {
|
|
||||||
current_chunk_ += count;
|
|
||||||
} else {
|
|
||||||
const auto added = count - (last_chunk_ - current_chunk_);
|
|
||||||
if (added >= ring_state_.size()) {
|
|
||||||
ring_state_.set(0U, ring_state_.size(), true);
|
|
||||||
current_chunk_ += count;
|
|
||||||
first_chunk_ += added;
|
|
||||||
last_chunk_ =
|
|
||||||
std::min(total_chunks_ - 1U, first_chunk_ + ring_state_.size() - 1U);
|
|
||||||
} else {
|
|
||||||
for (std::size_t idx = 0U; idx < added; ++idx) {
|
|
||||||
ring_state_[(first_chunk_ + idx) % ring_state_.size()] = true;
|
|
||||||
}
|
|
||||||
first_chunk_ += added;
|
|
||||||
current_chunk_ += count;
|
|
||||||
last_chunk_ =
|
|
||||||
std::min(total_chunks_ - 1U, first_chunk_ + ring_state_.size() - 1U);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
chunk_notify_.notify_all();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ring_buffer_open_file::get_read_state() const -> boost::dynamic_bitset<> {
|
|
||||||
recur_mutex_lock file_lock(file_mtx_);
|
|
||||||
auto read_state = ring_state_;
|
|
||||||
return read_state.flip();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ring_buffer_open_file::get_read_state(std::size_t chunk) const -> bool {
|
|
||||||
recur_mutex_lock file_lock(file_mtx_);
|
|
||||||
return not ring_state_[chunk % ring_state_.size()];
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ring_buffer_open_file::is_download_complete() const -> bool {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ring_buffer_open_file::native_operation(
|
auto ring_buffer_open_file::native_operation(
|
||||||
@ -203,121 +77,75 @@ auto ring_buffer_open_file::native_operation(
|
|||||||
return do_io([&]() -> api_error { return callback(nf_->get_handle()); });
|
return do_io([&]() -> api_error { return callback(nf_->get_handle()); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void ring_buffer_open_file::reverse(std::size_t count) {
|
auto ring_buffer_open_file::on_check_start() -> bool {
|
||||||
mutex_lock chunk_lock(chunk_mtx_);
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
if (current_chunk_ < count) {
|
|
||||||
count = current_chunk_;
|
if (nf_) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((current_chunk_ - count) >= first_chunk_) {
|
auto buffer_directory{utils::path::get_parent_path(source_path_)};
|
||||||
current_chunk_ -= count;
|
if (not utils::file::directory(buffer_directory).create_directory()) {
|
||||||
} else {
|
throw std::runtime_error(
|
||||||
const auto removed = count - (current_chunk_ - first_chunk_);
|
fmt::format("failed to create buffer directory|path|{}|err|{}",
|
||||||
if (removed >= ring_state_.size()) {
|
buffer_directory, utils::get_last_error_code()));
|
||||||
ring_state_.set(0U, ring_state_.size(), true);
|
|
||||||
current_chunk_ -= count;
|
|
||||||
first_chunk_ = current_chunk_;
|
|
||||||
last_chunk_ =
|
|
||||||
std::min(total_chunks_ - 1U, first_chunk_ + ring_state_.size() - 1U);
|
|
||||||
} else {
|
|
||||||
for (std::size_t idx = 0U; idx < removed; ++idx) {
|
|
||||||
ring_state_[(last_chunk_ - idx) % ring_state_.size()] = true;
|
|
||||||
}
|
|
||||||
first_chunk_ -= removed;
|
|
||||||
current_chunk_ -= count;
|
|
||||||
last_chunk_ =
|
|
||||||
std::min(total_chunks_ - 1U, first_chunk_ + ring_state_.size() - 1U);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk_notify_.notify_all();
|
nf_ = utils::file::file::open_or_create_file(source_path_);
|
||||||
|
if (not nf_ || not *nf_) {
|
||||||
|
throw std::runtime_error(fmt::format("failed to create buffer file|err|{}",
|
||||||
|
utils::get_last_error_code()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not nf_->truncate(get_ring_size() * get_chunk_size())) {
|
||||||
|
nf_->close();
|
||||||
|
nf_.reset();
|
||||||
|
|
||||||
|
throw std::runtime_error(fmt::format("failed to resize buffer file|err|{}",
|
||||||
|
utils::get_last_error_code()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ring_buffer_open_file::read(std::size_t read_size,
|
auto ring_buffer_open_file::on_chunk_downloaded(
|
||||||
std::uint64_t read_offset, data_buffer &data)
|
std::size_t chunk, const data_buffer &buffer) -> api_error {
|
||||||
-> api_error {
|
return do_io([&]() -> api_error {
|
||||||
if (fsi_.directory) {
|
std::size_t bytes_written{};
|
||||||
return api_error::invalid_operation;
|
if (nf_->write(buffer, (chunk % get_ring_size()) * get_chunk_size(),
|
||||||
}
|
&bytes_written)) {
|
||||||
|
|
||||||
reset_timeout();
|
|
||||||
|
|
||||||
read_size = utils::calculate_read_size(fsi_.size, read_size, read_offset);
|
|
||||||
if (read_size == 0U) {
|
|
||||||
return api_error::success;
|
return api_error::success;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto start_chunk_index =
|
return api_error::os_error;
|
||||||
static_cast<std::size_t>(read_offset / chunk_size_);
|
});
|
||||||
read_offset = read_offset - (start_chunk_index * chunk_size_);
|
}
|
||||||
data_buffer buffer(chunk_size_);
|
|
||||||
|
|
||||||
auto res = api_error::success;
|
auto ring_buffer_open_file::on_read_chunk(
|
||||||
for (std::size_t chunk = start_chunk_index;
|
std::size_t chunk, std::size_t read_size, std::uint64_t read_offset,
|
||||||
(res == api_error::success) && (read_size > 0U); ++chunk) {
|
data_buffer &data, std::size_t &bytes_read) -> api_error {
|
||||||
if (chunk > current_chunk_) {
|
data_buffer buffer(read_size);
|
||||||
forward(chunk - current_chunk_);
|
auto res = do_io([&]() -> api_error {
|
||||||
} else if (chunk < current_chunk_) {
|
return nf_->read(
|
||||||
reverse(current_chunk_ - chunk);
|
buffer,
|
||||||
}
|
(((chunk % get_ring_size()) * get_chunk_size()) + read_offset),
|
||||||
|
|
||||||
reset_timeout();
|
|
||||||
res = download_chunk(chunk);
|
|
||||||
if (res == api_error::success) {
|
|
||||||
const auto to_read = std::min(
|
|
||||||
static_cast<std::size_t>(chunk_size_ - read_offset), read_size);
|
|
||||||
res = do_io([this, &buffer, &chunk, &data, read_offset,
|
|
||||||
&to_read]() -> api_error {
|
|
||||||
std::size_t bytes_read{};
|
|
||||||
auto ret =
|
|
||||||
nf_->read(buffer, ((chunk % ring_state_.size()) * chunk_size_),
|
|
||||||
&bytes_read)
|
&bytes_read)
|
||||||
? api_error::success
|
? api_error::success
|
||||||
: api_error::os_error;
|
: api_error::os_error;
|
||||||
if (ret == api_error::success) {
|
|
||||||
data.insert(data.end(),
|
|
||||||
buffer.begin() + static_cast<std::int64_t>(read_offset),
|
|
||||||
buffer.begin() +
|
|
||||||
static_cast<std::int64_t>(read_offset + to_read));
|
|
||||||
reset_timeout();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
});
|
});
|
||||||
read_offset = 0U;
|
|
||||||
read_size -= to_read;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (res != api_error::success) {
|
||||||
return res;
|
return res;
|
||||||
}
|
|
||||||
|
|
||||||
void ring_buffer_open_file::set(std::size_t first_chunk,
|
|
||||||
std::size_t current_chunk) {
|
|
||||||
mutex_lock chunk_lock(chunk_mtx_);
|
|
||||||
if (first_chunk >= total_chunks_) {
|
|
||||||
chunk_notify_.notify_all();
|
|
||||||
throw std::runtime_error("first chunk must be less than total chunks");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
first_chunk_ = first_chunk;
|
data.insert(data.end(), buffer.begin(), buffer.end());
|
||||||
last_chunk_ = first_chunk_ + ring_state_.size() - 1U;
|
return api_error::success;
|
||||||
|
|
||||||
if (current_chunk > last_chunk_) {
|
|
||||||
chunk_notify_.notify_all();
|
|
||||||
throw std::runtime_error(
|
|
||||||
"current chunk must be less than or equal to last chunk");
|
|
||||||
}
|
|
||||||
|
|
||||||
current_chunk_ = current_chunk;
|
|
||||||
ring_state_.set(0U, ring_state_.size(), false);
|
|
||||||
|
|
||||||
chunk_notify_.notify_all();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ring_buffer_open_file::set_api_path(const std::string &api_path) {
|
auto ring_buffer_open_file::use_buffer(
|
||||||
mutex_lock chunk_lock(chunk_mtx_);
|
std::size_t /* chunk */,
|
||||||
open_file_base::set_api_path(api_path);
|
std::function<api_error(data_buffer &)> func) -> api_error {
|
||||||
chunk_notify_.notify_all();
|
data_buffer buffer;
|
||||||
|
return func(buffer);
|
||||||
}
|
}
|
||||||
} // namespace repertory
|
} // namespace repertory
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user