35 Commits

Author SHA1 Message Date
6464c01d8b updated CHANGELOG.md
Some checks failed
BlockStorage/repertory/pipeline/head There was a failure building this commit
2025-01-22 14:44:36 -06:00
58db36d628 updated CHANGELOG.md 2025-01-22 13:39:40 -06:00
f39c6550f2 refactor 2025-01-22 13:37:48 -06:00
400c97cebd refactor 2025-01-22 13:29:08 -06:00
a2ad258b7c refactor 2025-01-22 13:23:52 -06:00
c4b4fe83fb refactor 2025-01-22 13:21:44 -06:00
262fccf9a6 refactor 2025-01-22 13:21:31 -06:00
50898488f0 refactor 2025-01-22 13:13:36 -06:00
1acb3311b1 refactor 2025-01-22 13:12:18 -06:00
3fd3f85cc9 refactor 2025-01-22 13:07:10 -06:00
cbbd586347 refactor 2025-01-22 13:01:36 -06:00
57a591c51e refactor 2025-01-22 12:58:02 -06:00
29fb395758 revert change 2025-01-22 12:47:24 -06:00
b3f87e2828 refactor 2025-01-22 12:42:00 -06:00
7e06f810ea refactor 2025-01-22 12:41:28 -06:00
02e568b77a fix memory leak 2025-01-22 12:37:00 -06:00
8b2bafc9f3 refactor 2025-01-22 08:47:56 -06:00
97e5f17049 refactor 2025-01-22 08:06:54 -06:00
124dc62250 refactor 2025-01-22 08:05:35 -06:00
5da4d4e940 refactor 2025-01-22 08:01:35 -06:00
b507643d23 limit directory cache to directory operations 2025-01-22 07:39:41 -06:00
1e25fb57f1 refactor 2025-01-22 07:31:02 -06:00
4d8e59f97f refactor 2025-01-22 07:24:25 -06:00
881778e485 refactor events 2025-01-22 07:14:21 -06:00
3efb2b817f refactor 2025-01-21 15:24:39 -06:00
21d02534e5 refactor system stop 2025-01-21 15:19:33 -06:00
1b11e500f3 refactor winfsp system stop 2025-01-21 15:05:04 -06:00
f57bbdbb50 refactor 2025-01-21 14:59:11 -06:00
1c65f51ef4 refactor system stop 2025-01-21 14:57:13 -06:00
f44bb6bcfc force stop 2025-01-21 14:52:51 -06:00
57d9884510 refactor 2025-01-21 13:46:51 -06:00
5da036e979 refactor system stop 2025-01-21 13:29:56 -06:00
daa8b9df24 refactor system stop 2025-01-21 13:18:22 -06:00
fe2a1b96b2 rocksdb cache adjustments 2025-01-21 09:23:43 -06:00
be678e8f9c refactor 2025-01-21 08:01:15 -06:00
77 changed files with 1306 additions and 1077 deletions

View File

@ -11,7 +11,7 @@
* \#28 \[bug\] Address slow directory responses in S3 mounts for deeply nested directories
* \#29 \[bug\] S3 error responses are not being logged
* \#30 \[bug\] Sia provider error responses are not logged
* ~~\#31 \[bug\] S3 provider should limit max key size to 1024~~
* \#31 \[bug\] S3 provider should limit max key size to 1024
### Changes from v2.0.2-rc
@ -19,6 +19,8 @@
* Fixed http headers not being added for requests
* Fixed incorrect `stat` values for remote mounts
* Fixed invalid directory nullptr error on remote mounts
* Fixed memory leak in event system
* Refactored application shutdown
* Updated build system to Alpine 3.21.0
* Updated build system to MinGW-w64 12.0.0
* Updated copyright to 2018-2025

View File

@ -1,15 +1,15 @@
set(BINUTILS_VERSION 2.43)
set(BOOST2_MAJOR_VERSION 1)
set(BOOST2_MINOR_VERSION 76)
set(BOOST2_PATCH_VERSION 0)
set(BOOST_MAJOR_VERSION 1)
set(BOOST_MINOR_VERSION 87)
set(BOOST_PATCH_VERSION 0)
set(BOOST2_MAJOR_VERSION 1)
set(BOOST2_MINOR_VERSION 76)
set(BOOST2_PATCH_VERSION 0)
set(CPP_HTTPLIB_VERSION 0.18.1)
set(CURL2_VERSION 8_11_0)
set(CURL_VERSION 8.11.0)
set(EXPAT2_VERSION 2_6_4)
set(CURL2_VERSION 8_11_0)
set(EXPAT_VERSION 2.6.4)
set(EXPAT2_VERSION 2_6_4)
set(GCC_VERSION 14.2.0)
set(GTEST_VERSION 1.15.2)
set(ICU_VERSION 76-1)
@ -22,7 +22,7 @@ set(PKG_CONFIG_VERSION 0.29.2)
set(PUGIXML_VERSION 1.14)
set(ROCKSDB_VERSION 9.7.4)
set(SPDLOG_VERSION 1.15.0)
set(SQLITE2_VERSION 3.46.1)
set(SQLITE_VERSION 3460100)
set(SQLITE2_VERSION 3.46.1)
set(STDUUID_VERSION 1.2.3)
set(ZLIB_VERSION 1.3.1)

View File

@ -28,27 +28,35 @@
namespace repertory {
class app_config final {
private:
static stop_type stop_requested;
public:
[[nodiscard]] static auto
default_agent_name(const provider_type &prov) -> std::string;
[[nodiscard]] static auto default_agent_name(const provider_type &prov)
-> std::string;
[[nodiscard]] static auto
default_api_port(const provider_type &prov) -> std::uint16_t;
[[nodiscard]] static auto default_api_port(const provider_type &prov)
-> std::uint16_t;
[[nodiscard]] static auto
default_data_directory(const provider_type &prov) -> std::string;
[[nodiscard]] static auto default_data_directory(const provider_type &prov)
-> std::string;
[[nodiscard]] static auto
default_remote_api_port(const provider_type &prov) -> std::uint16_t;
[[nodiscard]] static auto default_remote_api_port(const provider_type &prov)
-> std::uint16_t;
[[nodiscard]] static auto
default_rpc_port(const provider_type &prov) -> std::uint16_t;
[[nodiscard]] static auto default_rpc_port(const provider_type &prov)
-> std::uint16_t;
[[nodiscard]] static auto
get_provider_display_name(const provider_type &prov) -> std::string;
[[nodiscard]] static auto get_provider_display_name(const provider_type &prov)
-> std::string;
[[nodiscard]] static auto
get_provider_name(const provider_type &prov) -> std::string;
[[nodiscard]] static auto get_provider_name(const provider_type &prov)
-> std::string;
public:
[[nodiscard]] static auto get_stop_requested() -> bool;
static void set_stop_requested();
public:
app_config(const provider_type &prov, std::string_view data_directory = "");
@ -185,8 +193,8 @@ public:
[[nodiscard]] auto get_task_wait_ms() const -> std::uint16_t;
[[nodiscard]] auto
get_value_by_name(const std::string &name) const -> std::string;
[[nodiscard]] auto get_value_by_name(const std::string &name) const
-> std::string;
[[nodiscard]] auto get_version() const -> std::uint64_t;

View File

@ -22,6 +22,7 @@
#ifndef REPERTORY_INCLUDE_COMM_CURL_CURL_COMM_HPP_
#define REPERTORY_INCLUDE_COMM_CURL_CURL_COMM_HPP_
#include "app_config.hpp"
#include "comm/curl/multi_request.hpp"
#include "comm/i_http_comm.hpp"
#include "events/event_system.hpp"
@ -42,7 +43,7 @@ private:
struct read_write_info final {
data_buffer data{};
stop_type &stop_requested;
stop_type_callback stop_requested_cb;
};
static const write_callback write_data;
@ -115,7 +116,7 @@ public:
return false;
}
if (response_code != 200) {
if (response_code != http_error_codes::ok) {
return false;
}
@ -170,7 +171,12 @@ public:
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, write_headers);
}
read_write_info write_info{{}, stop_requested};
read_write_info write_info{
{},
[&stop_requested]() -> bool {
return stop_requested || app_config::get_stop_requested();
},
};
if (request.response_handler.has_value()) {
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_info);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);

View File

@ -36,6 +36,9 @@ private:
stop_type &stop_requested_;
CURLM *multi_handle_;
private:
[[nodiscard]] auto get_stop_requested() const -> bool;
public:
void get_result(CURLcode &curl_code, long &http_code);
};

View File

@ -58,7 +58,7 @@ public:
virtual void enumerate_item_list(
std::function<void(const std::vector<i_file_db::file_info> &)> callback,
stop_type &stop_requested) const = 0;
stop_type_callback stop_requested_cb) const = 0;
[[nodiscard]] virtual auto get_api_path(const std::string &source_path,
std::string &api_path) const
@ -84,7 +84,8 @@ public:
get_file_source_path(const std::string &api_path,
std::string &source_path) const -> api_error = 0;
[[nodiscard]] virtual auto get_item_list(stop_type &stop_requested) const
[[nodiscard]] virtual auto
get_item_list(stop_type_callback stop_requested_cb) const
-> std::vector<file_info> = 0;
[[nodiscard]] virtual auto get_source_path(const std::string &api_path,

View File

@ -33,7 +33,7 @@ public:
virtual void enumerate_api_path_list(
std::function<void(const std::vector<std::string> &)> callback,
stop_type &stop_requested) const = 0;
stop_type_callback stop_requested_cb) const = 0;
[[nodiscard]] virtual auto get_api_path(const std::string &source_path,
std::string &api_path) const

View File

@ -80,7 +80,7 @@ public:
void enumerate_item_list(
std::function<void(const std::vector<i_file_db::file_info> &)> callback,
stop_type &stop_requested) const override;
stop_type_callback stop_requested_cb) const override;
[[nodiscard]] auto get_api_path(const std::string &source_path,
std::string &api_path) const
@ -106,7 +106,7 @@ public:
std::string &source_path) const
-> api_error override;
[[nodiscard]] auto get_item_list(stop_type &stop_requested) const
[[nodiscard]] auto get_item_list(stop_type_callback stop_requested_cb) const
-> std::vector<i_file_db::file_info> override;
[[nodiscard]] auto get_source_path(const std::string &api_path,

View File

@ -82,7 +82,7 @@ public:
void enumerate_api_path_list(
std::function<void(const std::vector<std::string> &)> callback,
stop_type &stop_requested) const override;
stop_type_callback stop_requested_cb) const override;
[[nodiscard]] auto get_api_path(const std::string &source_path,
std::string &api_path) const

View File

@ -55,7 +55,7 @@ public:
void enumerate_item_list(
std::function<void(const std::vector<i_file_db::file_info> &)> callback,
stop_type &stop_requested) const override;
stop_type_callback stop_requested_cb) const override;
[[nodiscard]] auto get_api_path(const std::string &source_path,
std::string &api_path) const
@ -81,7 +81,7 @@ public:
std::string &source_path) const
-> api_error override;
[[nodiscard]] auto get_item_list(stop_type &stop_requested) const
[[nodiscard]] auto get_item_list(stop_type_callback stop_requested_cb) const
-> std::vector<i_file_db::file_info> override;
[[nodiscard]] auto get_source_path(const std::string &api_path,

View File

@ -52,7 +52,7 @@ public:
void enumerate_api_path_list(
std::function<void(const std::vector<std::string> &)> callback,
stop_type &stop_requested) const override;
stop_type_callback stop_requested_cb) const override;
[[nodiscard]] auto get_api_path(const std::string &source_path,
std::string &api_path) const

View File

@ -22,12 +22,10 @@
#ifndef REPERTORY_INCLUDE_DRIVES_DIRECTORY_CACHE_HPP_
#define REPERTORY_INCLUDE_DRIVES_DIRECTORY_CACHE_HPP_
#include "utils/single_thread_service_base.hpp"
namespace repertory {
class directory_iterator;
class directory_cache final : public single_thread_service_base {
class directory_cache final {
public:
using execute_callback = std::function<void(directory_iterator &)>;
@ -35,13 +33,11 @@ private:
struct open_directory final {
std::shared_ptr<directory_iterator> iterator;
std::vector<std::uint64_t> handles;
std::chrono::system_clock::time_point last_update{
std::chrono::system_clock::now()};
};
public:
directory_cache() : single_thread_service_base("directory_cache") {}
~directory_cache() override = default;
directory_cache() = default;
~directory_cache() = default;
directory_cache(const directory_cache &) = delete;
directory_cache(directory_cache &&) = delete;
@ -51,17 +47,13 @@ public:
private:
std::unordered_map<std::string, open_directory> directory_lookup_;
std::recursive_mutex directory_mutex_;
std::unique_ptr<std::thread> refresh_thread_;
protected:
void service_function() override;
public:
void execute_action(const std::string &api_path,
const execute_callback &execute);
[[nodiscard]] auto
get_directory(std::uint64_t handle) -> std::shared_ptr<directory_iterator>;
[[nodiscard]] auto get_directory(std::uint64_t handle)
-> std::shared_ptr<directory_iterator>;
auto remove_directory(const std::string &api_path)
-> std::shared_ptr<directory_iterator>;

View File

@ -26,13 +26,13 @@
namespace repertory {
// clang-format off
E_SIMPLE3(fuse_event, debug, true,
E_SIMPLE3(fuse_event, debug,
std::string, function, func, E_FROM_STRING,
std::string, api_path, ap, E_FROM_STRING,
int, result, res, E_FROM_INT32
);
E_SIMPLE1(fuse_args_parsed, info, true,
E_SIMPLE1(fuse_args_parsed, info,
std::string, arguments, args, E_FROM_STRING
);
// clang-format on

View File

@ -63,99 +63,103 @@ private:
std::shared_ptr<logging_consumer> logging_consumer_;
std::shared_ptr<remote_fuse::remote_server> remote_server_;
std::shared_ptr<full_server> server_;
bool was_mounted_ = false;
std::mutex stop_all_mtx_;
bool was_mounted_{false};
private:
void update_accessed_time(const std::string &api_path);
protected:
#if defined(__APPLE__)
[[nodiscard]] auto chflags_impl(std::string api_path,
uint32_t flags) -> api_error override;
[[nodiscard]] auto chflags_impl(std::string api_path, uint32_t flags)
-> api_error override;
#endif // __APPLE__
#if FUSE_USE_VERSION >= 30
[[nodiscard]] auto
chmod_impl(std::string api_path, mode_t mode,
struct fuse_file_info *file_info) -> api_error override;
[[nodiscard]] auto chmod_impl(std::string api_path, mode_t mode,
struct fuse_file_info *file_info)
-> api_error override;
#else
[[nodiscard]] auto chmod_impl(std::string api_path,
mode_t mode) -> api_error override;
[[nodiscard]] auto chmod_impl(std::string api_path, mode_t mode)
-> api_error override;
#endif
#if FUSE_USE_VERSION >= 30
[[nodiscard]] auto
chown_impl(std::string api_path, uid_t uid, gid_t gid,
struct fuse_file_info *file_info) -> api_error override;
[[nodiscard]] auto chown_impl(std::string api_path, uid_t uid, gid_t gid,
struct fuse_file_info *file_info)
-> api_error override;
#else
[[nodiscard]] auto chown_impl(std::string api_path, uid_t uid,
gid_t gid) -> api_error override;
[[nodiscard]] auto chown_impl(std::string api_path, uid_t uid, gid_t gid)
-> api_error override;
#endif
[[nodiscard]] auto
create_impl(std::string api_path, mode_t mode,
struct fuse_file_info *file_info) -> api_error override;
[[nodiscard]] auto create_impl(std::string api_path, mode_t mode,
struct fuse_file_info *file_info)
-> api_error override;
void destroy_impl(void *ptr) override;
[[nodiscard]] auto
fallocate_impl(std::string api_path, int mode, off_t offset, off_t length,
struct fuse_file_info *file_info) -> api_error override;
[[nodiscard]] auto fallocate_impl(std::string api_path, int mode,
off_t offset, off_t length,
struct fuse_file_info *file_info)
-> api_error override;
[[nodiscard]] auto
fgetattr_impl(std::string api_path, struct stat *unix_st,
struct fuse_file_info *file_info) -> api_error override;
[[nodiscard]] auto fgetattr_impl(std::string api_path, struct stat *unix_st,
struct fuse_file_info *file_info)
-> api_error override;
#if defined(__APPLE__)
[[nodiscard]] auto
fsetattr_x_impl(std::string api_path, struct setattr_x *attr,
struct fuse_file_info *file_info) -> api_error override;
[[nodiscard]] auto fsetattr_x_impl(std::string api_path,
struct setattr_x *attr,
struct fuse_file_info *file_info)
-> api_error override;
#endif // __APPLE__
[[nodiscard]] auto
fsync_impl(std::string api_path, int datasync,
struct fuse_file_info *file_info) -> api_error override;
[[nodiscard]] auto fsync_impl(std::string api_path, int datasync,
struct fuse_file_info *file_info)
-> api_error override;
#if FUSE_USE_VERSION < 30
[[nodiscard]] auto
ftruncate_impl(std::string api_path, off_t size,
struct fuse_file_info *file_info) -> api_error override;
[[nodiscard]] auto ftruncate_impl(std::string api_path, off_t size,
struct fuse_file_info *file_info)
-> api_error override;
#endif
#if FUSE_USE_VERSION >= 30
[[nodiscard]] auto
getattr_impl(std::string api_path, struct stat *unix_st,
struct fuse_file_info *file_info) -> api_error override;
[[nodiscard]] auto getattr_impl(std::string api_path, struct stat *unix_st,
struct fuse_file_info *file_info)
-> api_error override;
#else
[[nodiscard]] auto getattr_impl(std::string api_path,
struct stat *unix_st) -> api_error override;
[[nodiscard]] auto getattr_impl(std::string api_path, struct stat *unix_st)
-> api_error override;
#endif
#if defined(__APPLE__)
[[nodiscard]] auto
getxtimes_impl(std::string api_path, struct timespec *bkuptime,
struct timespec *crtime) -> api_error override;
[[nodiscard]] auto getxtimes_impl(std::string api_path,
struct timespec *bkuptime,
struct timespec *crtime)
-> api_error override;
#endif // __APPLE__
#if FUSE_USE_VERSION >= 30
auto init_impl(struct fuse_conn_info *conn,
struct fuse_config *cfg) -> void * override;
auto init_impl(struct fuse_conn_info *conn, struct fuse_config *cfg)
-> void * override;
#else
auto init_impl(struct fuse_conn_info *conn) -> void * override;
#endif
[[nodiscard]] auto mkdir_impl(std::string api_path,
mode_t mode) -> api_error override;
[[nodiscard]] auto mkdir_impl(std::string api_path, mode_t mode)
-> api_error override;
void notify_fuse_main_exit(int &ret) override;
[[nodiscard]] auto
open_impl(std::string api_path,
struct fuse_file_info *file_info) -> api_error override;
[[nodiscard]] auto open_impl(std::string api_path,
struct fuse_file_info *file_info)
-> api_error override;
[[nodiscard]] auto
opendir_impl(std::string api_path,
struct fuse_file_info *file_info) -> api_error override;
[[nodiscard]] auto opendir_impl(std::string api_path,
struct fuse_file_info *file_info)
-> api_error override;
[[nodiscard]] auto read_impl(std::string api_path, char *buffer,
size_t read_size, off_t read_offset,
@ -163,29 +167,30 @@ protected:
std::size_t &bytes_read) -> api_error override;
#if FUSE_USE_VERSION >= 30
[[nodiscard]] auto
readdir_impl(std::string api_path, void *buf, fuse_fill_dir_t fuse_fill_dir,
off_t offset, struct fuse_file_info *file_info,
fuse_readdir_flags flags) -> api_error override;
[[nodiscard]] auto readdir_impl(std::string api_path, void *buf,
fuse_fill_dir_t fuse_fill_dir, off_t offset,
struct fuse_file_info *file_info,
fuse_readdir_flags flags)
-> api_error override;
#else
[[nodiscard]] auto
readdir_impl(std::string api_path, void *buf, fuse_fill_dir_t fuse_fill_dir,
off_t offset,
struct fuse_file_info *file_info) -> api_error override;
[[nodiscard]] auto readdir_impl(std::string api_path, void *buf,
fuse_fill_dir_t fuse_fill_dir, off_t offset,
struct fuse_file_info *file_info)
-> api_error override;
#endif
[[nodiscard]] auto
release_impl(std::string api_path,
struct fuse_file_info *file_info) -> api_error override;
[[nodiscard]] auto release_impl(std::string api_path,
struct fuse_file_info *file_info)
-> api_error override;
[[nodiscard]] auto
releasedir_impl(std::string api_path,
struct fuse_file_info *file_info) -> api_error override;
[[nodiscard]] auto releasedir_impl(std::string api_path,
struct fuse_file_info *file_info)
-> api_error override;
#if FUSE_USE_VERSION >= 30
[[nodiscard]] auto rename_impl(std::string from_api_path,
std::string to_api_path,
unsigned int flags) -> api_error override;
std::string to_api_path, unsigned int flags)
-> api_error override;
#else
[[nodiscard]] auto rename_impl(std::string from_api_path,
std::string to_api_path) -> api_error override;
@ -196,8 +201,8 @@ protected:
#if defined(HAS_SETXATTR)
[[nodiscard]] auto getxattr_common(std::string api_path, const char *name,
char *value, size_t size,
int &attribute_size,
uint32_t *position) -> api_error;
int &attribute_size, uint32_t *position)
-> api_error;
#if defined(__APPLE__)
[[nodiscard]] auto getxattr_impl(std::string api_path, const char *name,
@ -213,8 +218,8 @@ protected:
size_t size, int &required_size,
bool &return_size) -> api_error override;
[[nodiscard]] auto removexattr_impl(std::string api_path,
const char *name) -> api_error override;
[[nodiscard]] auto removexattr_impl(std::string api_path, const char *name)
-> api_error override;
#if defined(__APPLE__)
[[nodiscard]] auto setxattr_impl(std::string api_path, const char *name,
@ -222,62 +227,64 @@ protected:
uint32_t position) -> api_error override;
#else // __APPLE__
[[nodiscard]] auto setxattr_impl(std::string api_path, const char *name,
const char *value, size_t size,
int flags) -> api_error override;
const char *value, size_t size, int flags)
-> api_error override;
#endif // __APPLE__
#endif // HAS_SETXATTR
#if defined(__APPLE__)
[[nodiscard]] auto
setattr_x_impl(std::string api_path,
struct setattr_x *attr) -> api_error override;
[[nodiscard]] auto setattr_x_impl(std::string api_path,
struct setattr_x *attr)
-> api_error override;
[[nodiscard]] auto
setbkuptime_impl(std::string api_path,
const struct timespec *bkuptime) -> api_error override;
[[nodiscard]] auto setbkuptime_impl(std::string api_path,
const struct timespec *bkuptime)
-> api_error override;
[[nodiscard]] auto
setchgtime_impl(std::string api_path,
const struct timespec *chgtime) -> api_error override;
[[nodiscard]] auto setchgtime_impl(std::string api_path,
const struct timespec *chgtime)
-> api_error override;
[[nodiscard]] auto
setcrtime_impl(std::string api_path,
const struct timespec *crtime) -> api_error override;
[[nodiscard]] auto setcrtime_impl(std::string api_path,
const struct timespec *crtime)
-> api_error override;
[[nodiscard]] auto setvolname_impl(const char *volname) -> api_error override;
[[nodiscard]] auto statfs_x_impl(std::string api_path,
struct statfs *stbuf) -> api_error override;
[[nodiscard]] auto statfs_x_impl(std::string api_path, struct statfs *stbuf)
-> api_error override;
#else // __APPLE__
[[nodiscard]] auto statfs_impl(std::string api_path,
struct statvfs *stbuf) -> api_error override;
[[nodiscard]] auto statfs_impl(std::string api_path, struct statvfs *stbuf)
-> api_error override;
#endif // __APPLE__
#if FUSE_USE_VERSION >= 30
[[nodiscard]] auto
truncate_impl(std::string api_path, off_t size,
struct fuse_file_info *file_info) -> api_error override;
[[nodiscard]] auto truncate_impl(std::string api_path, off_t size,
struct fuse_file_info *file_info)
-> api_error override;
#else
[[nodiscard]] auto truncate_impl(std::string api_path,
off_t size) -> api_error override;
[[nodiscard]] auto truncate_impl(std::string api_path, off_t size)
-> api_error override;
#endif
[[nodiscard]] auto unlink_impl(std::string api_path) -> api_error override;
#if FUSE_USE_VERSION >= 30
[[nodiscard]] auto
utimens_impl(std::string api_path, const struct timespec tv[2],
struct fuse_file_info *file_info) -> api_error override;
[[nodiscard]] auto utimens_impl(std::string api_path,
const struct timespec tv[2],
struct fuse_file_info *file_info)
-> api_error override;
#else
[[nodiscard]] auto
utimens_impl(std::string api_path,
const struct timespec tv[2]) -> api_error override;
[[nodiscard]] auto utimens_impl(std::string api_path,
const struct timespec tv[2])
-> api_error override;
#endif
[[nodiscard]] auto
write_impl(std::string api_path, const char *buffer, size_t write_size,
off_t write_offset, struct fuse_file_info *file_info,
std::size_t &bytes_written) -> api_error override;
[[nodiscard]] auto write_impl(std::string api_path, const char *buffer,
size_t write_size, off_t write_offset,
struct fuse_file_info *file_info,
std::size_t &bytes_written)
-> api_error override;
public:
[[nodiscard]] auto get_directory_item_count(const std::string &api_path) const
@ -286,16 +293,17 @@ public:
[[nodiscard]] auto get_directory_items(const std::string &api_path) const
-> directory_item_list override;
[[nodiscard]] auto
get_file_size(const std::string &api_path) const -> std::uint64_t override;
[[nodiscard]] auto get_file_size(const std::string &api_path) const
-> std::uint64_t 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,
api_meta_map &meta) const
-> api_error override;
[[nodiscard]] auto
get_item_meta(const std::string &api_path, const std::string &name,
std::string &value) const -> api_error override;
[[nodiscard]] auto get_item_meta(const std::string &api_path,
const std::string &name,
std::string &value) const
-> api_error override;
[[nodiscard]] auto get_total_drive_space() const -> std::uint64_t override;
@ -306,16 +314,16 @@ public:
void get_volume_info(UINT64 &total_size, UINT64 &free_size,
std::string &volume_label) const override;
[[nodiscard]] auto
is_processing(const std::string &api_path) const -> bool override;
[[nodiscard]] auto is_processing(const std::string &api_path) const
-> bool override;
[[nodiscard]] auto
rename_directory(const std::string &from_api_path,
const std::string &to_api_path) -> int override;
[[nodiscard]] auto rename_directory(const std::string &from_api_path,
const std::string &to_api_path)
-> int override;
[[nodiscard]] auto rename_file(const std::string &from_api_path,
const std::string &to_api_path,
bool overwrite) -> int override;
const std::string &to_api_path, bool overwrite)
-> int override;
void set_item_meta(const std::string &api_path, const std::string &key,
const std::string &value) override;

View File

@ -73,6 +73,7 @@ private:
std::unique_ptr<file_manager> fm_;
std::unique_ptr<eviction> eviction_;
std::unique_ptr<remote_winfsp::remote_server> remote_server_;
std::mutex stop_all_mtx_;
private:
[[nodiscard]] auto handle_error(std::string_view function_name,
@ -94,6 +95,8 @@ private:
static void set_file_info(remote::file_info &dest,
const FSP_FSCTL_FILE_INFO &src);
void stop_all();
public:
auto CanDelete(PVOID file_node, PVOID file_desc, PWSTR file_name)
-> NTSTATUS override;

View File

@ -22,29 +22,15 @@
#ifndef REPERTORY_INCLUDE_EVENTS_EVENT_HPP_
#define REPERTORY_INCLUDE_EVENTS_EVENT_HPP_
#include "types/repertory.hpp"
namespace repertory {
enum class event_level {
critical,
error,
warn,
info,
debug,
trace,
};
[[nodiscard]] auto
event_level_from_string(std::string level,
event_level default_level = event_level::info)
-> event_level;
[[nodiscard]] auto event_level_to_string(event_level level) -> std::string;
class event {
protected:
explicit event(bool allow_async) : allow_async_(allow_async) {}
event() = default;
event(const std::stringstream &ss, json j, bool allow_async)
: allow_async_(allow_async), ss_(ss.str()), j_(std::move(j)) {}
event(const std::stringstream &ss, json j)
: ss_(ss.str()), j_(std::move(j)) {}
public:
event(const event &) = delete;
@ -53,18 +39,13 @@ public:
auto operator=(event &&) -> event & = delete;
virtual ~event() = default;
private:
bool allow_async_;
protected:
std::stringstream ss_;
json j_;
json j_{};
public:
[[nodiscard]] virtual auto clone() const -> std::shared_ptr<event> = 0;
[[nodiscard]] auto get_allow_async() const -> bool { return allow_async_; }
[[nodiscard]] virtual auto get_event_level() const -> event_level = 0;
[[nodiscard]] auto get_json() const -> json { return j_; }
@ -75,18 +56,4 @@ public:
};
} // 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_

View File

@ -24,6 +24,7 @@
#include "events/event.hpp"
#include "events/t_event_system.hpp"
#include "types/repertory.hpp"
namespace repertory {
using event_system = t_event_system<event>;
@ -60,8 +61,7 @@ public: \
#define E_BEGIN(name, el) \
class name final : public virtual event { \
private: \
name(const std::stringstream &ss, const json &j, bool allow_async) \
: event(ss, j, allow_async) {} \
name(const std::stringstream &ss, const json &j) : event(ss, j) {} \
\
public: \
~name() override = default; \
@ -84,28 +84,26 @@ public: \
} \
\
[[nodiscard]] auto clone() const -> std::shared_ptr<event> override { \
return std::shared_ptr<name>(new name(ss_, j_, get_allow_async())); \
return std::shared_ptr<name>(new name(ss_, j_)); \
}
#define E_END() }
#define E_SIMPLE(event_name, el, allow_async) \
#define E_SIMPLE(event_name, el) \
E_BEGIN(event_name, el) \
public: \
event_name() : event(allow_async) {} \
event_name() {} \
E_END()
#define E_SIMPLE1(event_name, el, allow_async, type, name, short_name, tc) \
#define E_SIMPLE1(event_name, el, type, name, short_name, tc) \
E_BEGIN(event_name, el) \
explicit event_name(const type &tv) : event(allow_async) { \
init_##short_name(tv); \
} \
explicit event_name(const type &tv) { init_##short_name(tv); } \
E_PROP(type, name, short_name, tc) \
E_END()
#define E_SIMPLE2(event_name, el, allow_async, type, name, short_name, tc, \
type2, name2, short_name2, tc2) \
#define E_SIMPLE2(event_name, el, type, name, short_name, tc, type2, name2, \
short_name2, tc2) \
E_BEGIN(event_name, el) \
explicit event_name(const type &tv, const type2 &tv2) : event(allow_async) { \
explicit event_name(const type &tv, const type2 &tv2) { \
init_##short_name(tv); \
init_##short_name2(tv2); \
} \
@ -113,12 +111,10 @@ public: \
E_PROP(type2, name2, short_name2, tc2) \
E_END()
#define E_SIMPLE3(event_name, el, allow_async, type, name, short_name, tc, \
type2, name2, short_name2, tc2, type3, name3, short_name3, \
tc3) \
#define E_SIMPLE3(event_name, el, type, name, short_name, tc, type2, name2, \
short_name2, tc2, type3, name3, short_name3, tc3) \
E_BEGIN(event_name, el) \
explicit event_name(const type &tv, const type2 &tv2, const type3 &tv3) \
: event(allow_async) { \
explicit event_name(const type &tv, const type2 &tv2, const type3 &tv3) { \
init_##short_name(tv); \
init_##short_name2(tv2); \
init_##short_name3(tv3); \
@ -128,13 +124,12 @@ public: \
E_PROP(type3, name3, short_name3, tc3) \
E_END()
#define E_SIMPLE4(event_name, el, allow_async, type, name, short_name, tc, \
type2, name2, short_name2, tc2, type3, name3, short_name3, \
tc3, type4, name4, short_name4, tc4) \
#define E_SIMPLE4(event_name, el, type, name, short_name, tc, type2, name2, \
short_name2, tc2, type3, name3, short_name3, tc3, type4, \
name4, short_name4, tc4) \
E_BEGIN(event_name, el) \
explicit event_name(const type &tv, const type2 &tv2, const type3 &tv3, \
const type4 &tv4) \
: event(allow_async) { \
const type4 &tv4) { \
init_##short_name(tv); \
init_##short_name2(tv2); \
init_##short_name3(tv3); \
@ -146,14 +141,12 @@ public: \
E_PROP(type4, name4, short_name4, tc4) \
E_END()
#define E_SIMPLE5(event_name, el, allow_async, type, name, short_name, tc, \
type2, name2, short_name2, tc2, type3, name3, short_name3, \
tc3, type4, name4, short_name4, tc4, type5, name5, \
short_name5, tc5) \
#define E_SIMPLE5(event_name, el, type, name, short_name, tc, type2, name2, \
short_name2, tc2, type3, name3, short_name3, tc3, type4, \
name4, short_name4, tc4, type5, name5, short_name5, tc5) \
E_BEGIN(event_name, el) \
explicit event_name(const type &tv, const type2 &tv2, const type3 &tv3, \
const type4 &tv4, const type5 &tv5) \
: event(allow_async) { \
const type4 &tv4, const type5 &tv5) { \
init_##short_name(tv); \
init_##short_name2(tv2); \
init_##short_name3(tv3); \
@ -167,14 +160,13 @@ public: \
E_PROP(type5, name5, short_name5, tc5) \
E_END()
#define E_SIMPLE6(event_name, el, allow_async, type, name, short_name, tc, \
type2, name2, short_name2, tc2, type3, name3, short_name3, \
tc3, type4, name4, short_name4, tc4, type5, name5, \
short_name5, tc5, type6, name6, short_name6, tc6) \
#define E_SIMPLE6(event_name, el, type, name, short_name, tc, type2, name2, \
short_name2, tc2, type3, name3, short_name3, tc3, type4, \
name4, short_name4, tc4, type5, name5, short_name5, tc5, \
type6, name6, short_name6, tc6) \
E_BEGIN(event_name, el) \
explicit event_name(const type &tv, const type2 &tv2, const type3 &tv3, \
const type4 &tv4, const type5 &tv5, const type6 &tv6) \
: event(allow_async) { \
const type4 &tv4, const type5 &tv5, const type6 &tv6) { \
init_##short_name(tv); \
init_##short_name2(tv2); \
init_##short_name3(tv3); \
@ -190,16 +182,15 @@ public: \
E_PROP(type6, name6, short_name6, tc6) \
E_END()
#define E_SIMPLE7(event_name, el, allow_async, type, name, short_name, tc, \
type2, name2, short_name2, tc2, type3, name3, short_name3, \
tc3, type4, name4, short_name4, tc4, type5, name5, \
short_name5, tc5, type6, name6, short_name6, tc6, type7, \
name7, short_name7, tc7) \
#define E_SIMPLE7(event_name, el, type, name, short_name, tc, type2, name2, \
short_name2, tc2, type3, name3, short_name3, tc3, type4, \
name4, short_name4, tc4, type5, name5, short_name5, tc5, \
type6, name6, short_name6, tc6, type7, name7, short_name7, \
tc7) \
E_BEGIN(event_name, el) \
explicit event_name(const type &tv, const type2 &tv2, const type3 &tv3, \
const type4 &tv4, const type5 &tv5, const type6 &tv6, \
const type7 &tv7) \
: event(allow_async) { \
const type7 &tv7) { \
init_##short_name(tv); \
init_##short_name2(tv2); \
init_##short_name3(tv3); \

View File

@ -28,126 +28,126 @@
namespace repertory {
// clang-format off
E_SIMPLE2(curl_error, error, true,
E_SIMPLE2(curl_error, error,
std::string, url, url, E_FROM_STRING,
CURLcode, res, res, E_FROM_CURL_CODE
);
E_SIMPLE3(debug_log, debug, true,
E_SIMPLE3(debug_log, debug,
std::string, function, func, E_FROM_STRING,
std::string, api_path, ap, E_FROM_STRING,
std::string, data, data, E_FROM_STRING
);
E_SIMPLE1(directory_removed, debug, true,
E_SIMPLE1(directory_removed, debug,
std::string, api_path, ap, E_FROM_STRING
);
E_SIMPLE2(directory_removed_externally, warn, true,
E_SIMPLE2(directory_removed_externally, warn,
std::string, api_path, ap, E_FROM_STRING,
std::string, source, src, E_FROM_STRING
);
E_SIMPLE2(directory_remove_failed, error, true,
E_SIMPLE2(directory_remove_failed, error,
std::string, api_path, ap, E_FROM_STRING,
std::string, error, err, E_FROM_STRING
);
E_SIMPLE2(drive_mount_failed, error, true,
E_SIMPLE2(drive_mount_failed, error,
std::string, location, loc, E_FROM_STRING,
std::string, result, res, E_FROM_STRING
);
E_SIMPLE1(drive_mounted, info, true,
E_SIMPLE1(drive_mounted, info,
std::string, location, loc, E_FROM_STRING
);
E_SIMPLE1(drive_mount_result, info, true,
E_SIMPLE1(drive_mount_result, info,
std::string, result, res, E_FROM_STRING
);
E_SIMPLE1(drive_unmount_pending, info, true,
E_SIMPLE1(drive_unmount_pending, info,
std::string, location, loc, E_FROM_STRING
);
E_SIMPLE1(drive_unmounted, info, true,
E_SIMPLE1(drive_unmounted, info,
std::string, location, loc, E_FROM_STRING
);
E_SIMPLE1(event_level_changed, info, true,
E_SIMPLE1(event_level_changed, info,
std::string, new_event_level, level, E_FROM_STRING
);
E_SIMPLE1(failed_upload_queued, error, true,
E_SIMPLE1(failed_upload_queued, error,
std::string, api_path, ap, E_FROM_STRING
);
E_SIMPLE1(failed_upload_removed, warn, true,
E_SIMPLE1(failed_upload_removed, warn,
std::string, api_path, ap, E_FROM_STRING
);
E_SIMPLE1(failed_upload_retry, info, true,
E_SIMPLE1(failed_upload_retry, info,
std::string, api_path, ap, E_FROM_STRING
);
E_SIMPLE2(file_get_failed, error, true,
E_SIMPLE2(file_get_failed, error,
std::string, api_path, ap, E_FROM_STRING,
std::string, error, err, E_FROM_STRING
);
E_SIMPLE1(file_get_api_list_failed, error, true,
E_SIMPLE1(file_get_api_list_failed, error,
std::string, error, err, E_FROM_STRING
);
E_SIMPLE1(file_pinned, info, true,
E_SIMPLE1(file_pinned, info,
std::string, api_path, ap, E_FROM_STRING
);
E_SIMPLE3(file_read_bytes_failed, error, true,
E_SIMPLE3(file_read_bytes_failed, error,
std::string, api_path, ap, E_FROM_STRING,
std::string, error, err, E_FROM_STRING,
std::size_t, retry, retry, E_FROM_SIZE_T
);
E_SIMPLE1(file_removed, debug, true,
E_SIMPLE1(file_removed, debug,
std::string, api_path, ap, E_FROM_STRING
);
E_SIMPLE2(file_removed_externally, warn, true,
E_SIMPLE2(file_removed_externally, warn,
std::string, api_path, ap, E_FROM_STRING,
std::string, source, src, E_FROM_STRING
);
E_SIMPLE2(file_remove_failed, error, true,
E_SIMPLE2(file_remove_failed, error,
std::string, api_path, ap, E_FROM_STRING,
std::string, error, err, E_FROM_STRING
);
E_SIMPLE3(file_rename_failed, error, true,
E_SIMPLE3(file_rename_failed, error,
std::string, from_api_path, FROM, E_FROM_STRING,
std::string, to_api_path, TO, E_FROM_STRING,
std::string, error, err, E_FROM_STRING
);
E_SIMPLE2(file_get_size_failed, error, true,
E_SIMPLE2(file_get_size_failed, error,
std::string, api_path, ap, E_FROM_STRING,
std::string, error, err, E_FROM_STRING
);
E_SIMPLE3(filesystem_item_added, debug, true,
E_SIMPLE3(filesystem_item_added, debug,
std::string, api_path, ap, E_FROM_STRING,
std::string, parent, parent, E_FROM_STRING,
bool, directory, dir, E_FROM_BOOL
);
E_SIMPLE4(filesystem_item_closed, trace, true,
E_SIMPLE4(filesystem_item_closed, trace,
std::string, api_path, ap, E_FROM_STRING,
std::string, source, src, E_FROM_STRING,
bool, directory, dir, E_FROM_BOOL,
bool, changed, changed, E_FROM_BOOL
);
E_SIMPLE5(filesystem_item_handle_closed, trace, true,
E_SIMPLE5(filesystem_item_handle_closed, trace,
std::string, api_path, ap, E_FROM_STRING,
std::uint64_t, handle, handle, E_FROM_UINT64,
std::string, source, src, E_FROM_STRING,
@ -155,136 +155,136 @@ E_SIMPLE5(filesystem_item_handle_closed, trace, true,
bool, changed, changed, E_FROM_BOOL
);
E_SIMPLE4(filesystem_item_handle_opened, trace, true,
E_SIMPLE4(filesystem_item_handle_opened, trace,
std::string, api_path, ap, E_FROM_STRING,
std::uint64_t, handle, handle, E_FROM_UINT64,
std::string, source, src, E_FROM_STRING,
bool, directory, dir, E_FROM_BOOL
);
E_SIMPLE2(filesystem_item_evicted, info, true,
E_SIMPLE2(filesystem_item_evicted, info,
std::string, api_path, ap, E_FROM_STRING,
std::string, source, src, E_FROM_STRING
);
E_SIMPLE3(filesystem_item_opened, trace, true,
E_SIMPLE3(filesystem_item_opened, trace,
std::string, api_path, ap, E_FROM_STRING,
std::string, source, src, E_FROM_STRING,
bool, directory, dir, E_FROM_BOOL
);
E_SIMPLE1(file_unpinned, info, true,
E_SIMPLE1(file_unpinned, info,
std::string, api_path, ap, E_FROM_STRING
);
E_SIMPLE4(file_upload_completed, info, true,
E_SIMPLE4(file_upload_completed, info,
std::string, api_path, ap, E_FROM_STRING,
std::string, source, src, E_FROM_STRING,
api_error, result, res, E_FROM_API_FILE_ERROR,
bool, cancelled, cancel, E_FROM_BOOL
);
E_SIMPLE3(file_upload_failed, error, true,
E_SIMPLE3(file_upload_failed, error,
std::string, api_path, ap, E_FROM_STRING,
std::string, source, src, E_FROM_STRING,
std::string, error, err, E_FROM_STRING
);
E_SIMPLE2(file_upload_not_found, warn, true,
E_SIMPLE2(file_upload_not_found, warn,
std::string, api_path, ap, E_FROM_STRING,
std::string, source, src, E_FROM_STRING
);
E_SIMPLE2(file_upload_queued, info, true,
E_SIMPLE2(file_upload_queued, info,
std::string, api_path, ap, E_FROM_STRING,
std::string, source, src, E_FROM_STRING
);
E_SIMPLE1(file_upload_removed, debug, true,
E_SIMPLE1(file_upload_removed, debug,
std::string, api_path, ap, E_FROM_STRING
);
E_SIMPLE3(file_upload_retry, info, true,
E_SIMPLE3(file_upload_retry, info,
std::string, api_path, ap, E_FROM_STRING,
std::string, source, src, E_FROM_STRING,
api_error, result, res, E_FROM_API_FILE_ERROR
);
E_SIMPLE2(file_upload_started, info, true,
E_SIMPLE2(file_upload_started, info,
std::string, api_path, ap, E_FROM_STRING,
std::string, source, src, E_FROM_STRING
);
E_SIMPLE1(orphaned_file_deleted, warn, true,
E_SIMPLE1(orphaned_file_deleted, warn,
std::string, source, src, E_FROM_STRING
);
E_SIMPLE1(orphaned_file_detected, warn, true,
E_SIMPLE1(orphaned_file_detected, warn,
std::string, source, src, E_FROM_STRING
);
E_SIMPLE3(orphaned_file_processing_failed, error, true,
E_SIMPLE3(orphaned_file_processing_failed, error,
std::string, source, src, E_FROM_STRING,
std::string, dest, dest, E_FROM_STRING,
std::string, result, res, E_FROM_STRING
);
E_SIMPLE1(orphaned_source_file_detected, info, true,
E_SIMPLE1(orphaned_source_file_detected, info,
std::string, source, src, E_FROM_STRING
);
E_SIMPLE1(orphaned_source_file_removed, info, true,
E_SIMPLE1(orphaned_source_file_removed, info,
std::string, source, src, E_FROM_STRING
);
E_SIMPLE1(polling_item_begin, debug, true,
E_SIMPLE1(polling_item_begin, debug,
std::string, item_name, item, E_FROM_STRING
);
E_SIMPLE1(polling_item_end, debug, true,
E_SIMPLE1(polling_item_end, debug,
std::string, item_name, item, E_FROM_STRING
);
E_SIMPLE2(provider_offline, error, true,
E_SIMPLE2(provider_offline, error,
std::string, host_name_or_ip, host, E_FROM_STRING,
std::uint16_t, port, port, E_FROM_UINT16
);
E_SIMPLE2(provider_upload_begin, info, true,
E_SIMPLE2(provider_upload_begin, info,
std::string, api_path, ap, E_FROM_STRING,
std::string, source, src, E_FROM_STRING
);
E_SIMPLE3(provider_upload_end, info, true,
E_SIMPLE3(provider_upload_end, info,
std::string, api_path, ap, E_FROM_STRING,
std::string, source, src, E_FROM_STRING,
api_error, result, res, E_FROM_API_FILE_ERROR
);
E_SIMPLE2(repertory_exception, error, true,
E_SIMPLE2(repertory_exception, error,
std::string, function, func, E_FROM_STRING,
std::string, message, msg, E_FROM_STRING
);
E_SIMPLE1(rpc_server_exception, error, true,
E_SIMPLE1(rpc_server_exception, error,
std::string, exception, exception, E_FROM_STRING
);
E_SIMPLE1(service_shutdown_begin, debug, true,
E_SIMPLE1(service_shutdown_begin, debug,
std::string, service, svc, E_FROM_STRING
);
E_SIMPLE1(service_shutdown_end, debug, true,
E_SIMPLE1(service_shutdown_end, debug,
std::string, service, svc, E_FROM_STRING
);
E_SIMPLE1(service_started, debug, true,
E_SIMPLE1(service_started, debug,
std::string, service, svc, E_FROM_STRING
);
E_SIMPLE(unmount_requested, info, true);
E_SIMPLE(unmount_requested, info);
#if !defined(_WIN32)
E_SIMPLE2(unmount_result, info, true,
E_SIMPLE2(unmount_result, info,
std::string, location, loc, E_FROM_STRING,
std::string, result, res, E_FROM_STRING
);

View File

@ -22,12 +22,26 @@
#ifndef REPERTORY_INCLUDE_EVENTS_T_EVENT_SYSTEM_HPP_
#define REPERTORY_INCLUDE_EVENTS_T_EVENT_SYSTEM_HPP_
#include "app_config.hpp"
#include "events/event.hpp"
#include "utils/collection.hpp"
#include "utils/utils.hpp"
namespace repertory {
template <typename event_type> class t_event_system final {
private:
static constexpr const std::uint8_t max_queue_retry{
30U,
};
const std::uint32_t max_queue_size{
std::thread::hardware_concurrency() * 4UL,
};
static constexpr const std::chrono::seconds queue_wait_secs{
5s,
};
public:
t_event_system(const t_event_system &) = delete;
t_event_system(t_event_system &&) = delete;
@ -83,38 +97,48 @@ private:
std::mutex event_mutex_;
std::unique_ptr<std::thread> event_thread_;
std::mutex run_mutex_;
stop_type stop_requested_ = false;
stop_type stop_requested_{false};
private:
[[nodiscard]] auto get_stop_requested() const -> bool {
return stop_requested_ || app_config::get_stop_requested();
}
void process_events() {
std::vector<std::shared_ptr<event_type>> events;
{
unique_mutex_lock lock(event_mutex_);
if (not stop_requested_ && event_list_.empty()) {
event_notify_.wait_for(lock, 1s);
}
if (not event_list_.empty()) {
events.insert(events.end(), event_list_.begin(), event_list_.end());
event_list_.clear();
}
unique_mutex_lock lock(event_mutex_);
const auto lock_and_notify = [this, &lock]() {
lock.lock();
event_notify_.notify_all();
lock.unlock();
};
if (not get_stop_requested() && event_list_.empty()) {
event_notify_.wait_for(lock, queue_wait_secs);
}
if (not event_list_.empty()) {
events.insert(events.end(), event_list_.begin(), event_list_.end());
event_list_.clear();
}
lock.unlock();
if (events.empty()) {
lock_and_notify();
return;
}
const auto notify_events = [this](const std::string &name,
const event_type &event) {
std::deque<std::future<void>> futures;
recur_mutex_lock lock(consumer_mutex_);
if (event_consumers_.find(name) != event_consumers_.end()) {
for (auto *consumer : event_consumers_[name]) {
if (event.get_allow_async()) {
futures.emplace_back(
std::async(std::launch::async, [consumer, &event]() {
consumer->notify_event(event);
}));
} else {
consumer->notify_event(event);
}
}
recur_mutex_lock consumer_lock(consumer_mutex_);
for (auto *consumer : event_consumers_[name]) {
futures.emplace_back(
std::async(std::launch::async, [consumer, &event]() {
consumer->notify_event(event);
}));
}
while (not futures.empty()) {
@ -127,12 +151,31 @@ private:
notify_events("", *evt.get());
notify_events(evt->get_name(), *evt.get());
}
lock_and_notify();
}
void queue_event(std::shared_ptr<event_type> evt) {
mutex_lock lock(event_mutex_);
unique_mutex_lock lock(event_mutex_);
event_list_.push_back(std::move(evt));
auto size = event_list_.size();
event_notify_.notify_all();
lock.unlock();
for (std::uint8_t retry{0U};
size > max_queue_size && retry < max_queue_retry &&
not get_stop_requested();
++retry) {
lock.lock();
size = event_list_.size();
if (size > max_queue_size) {
event_notify_.wait_for(lock, queue_wait_secs);
size = event_list_.size();
}
event_notify_.notify_all();
lock.unlock();
}
}
public:
@ -165,27 +208,40 @@ public:
void start() {
mutex_lock lock(run_mutex_);
if (not event_thread_) {
stop_requested_ = false;
event_thread_ = std::make_unique<std::thread>([this]() {
while (not stop_requested_) {
process_events();
}
});
if (event_thread_) {
event_notify_.notify_all();
return;
}
stop_requested_ = false;
event_thread_ = std::make_unique<std::thread>([this]() {
while (not get_stop_requested()) {
process_events();
}
});
event_notify_.notify_all();
}
void stop() {
mutex_lock lock(run_mutex_);
if (event_thread_) {
stop_requested_ = true;
unique_mutex_lock lock(run_mutex_);
if (not event_thread_) {
event_notify_.notify_all();
event_thread_->join();
event_thread_.reset();
process_events();
return;
}
stop_requested_ = true;
std::unique_ptr<std::thread> thread{nullptr};
std::swap(thread, event_thread_);
event_notify_.notify_all();
lock.unlock();
thread->join();
thread.reset();
process_events();
}
};
} // namespace repertory

View File

@ -28,6 +28,11 @@ namespace repertory {
class app_config;
class cache_size_mgr final {
private:
static constexpr const std::chrono::seconds cache_wait_secs{
5s,
};
public:
cache_size_mgr(const cache_size_mgr &) = delete;
cache_size_mgr(cache_size_mgr &&) = delete;
@ -49,6 +54,9 @@ private:
std::condition_variable notify_;
stop_type stop_requested_{false};
private:
[[nodiscard]] auto get_stop_requested() const -> bool;
public:
[[nodiscard]] auto expand(std::uint64_t size) -> api_error;

View File

@ -27,55 +27,55 @@
namespace repertory {
// clang-format off
E_SIMPLE2(download_begin, info, true,
E_SIMPLE2(download_begin, info,
std::string, api_path, ap, E_FROM_STRING,
std::string, dest_path, dest, E_FROM_STRING
);
E_SIMPLE3(download_end, info, true,
E_SIMPLE3(download_end, info,
std::string, api_path, ap, E_FROM_STRING,
std::string, dest_path, dest, E_FROM_STRING,
api_error, result, result, E_FROM_API_FILE_ERROR
);
E_SIMPLE3(download_progress, info, true,
E_SIMPLE3(download_progress, info,
std::string, api_path, ap, E_FROM_STRING,
std::string, dest_path, dest, E_FROM_STRING,
double, progress, prog, E_FROM_DOUBLE_PRECISE
);
E_SIMPLE2(download_restored, info, true,
E_SIMPLE2(download_restored, info,
std::string, api_path, ap, E_FROM_STRING,
std::string, dest_path, dest, E_FROM_STRING
);
E_SIMPLE3(download_restore_failed, error, true,
E_SIMPLE3(download_restore_failed, error,
std::string, api_path, ap, E_FROM_STRING,
std::string, dest_path, dest, E_FROM_STRING,
std::string, error, err, E_FROM_STRING
);
E_SIMPLE3(download_resume_add_failed, error, true,
E_SIMPLE3(download_resume_add_failed, error,
std::string, api_path, ap, E_FROM_STRING,
std::string, dest_path, dest, E_FROM_STRING,
std::string, error, err, E_FROM_STRING
);
E_SIMPLE2(download_resume_added, debug, true,
E_SIMPLE2(download_resume_added, debug,
std::string, api_path, ap, E_FROM_STRING,
std::string, dest_path, dest, E_FROM_STRING
);
E_SIMPLE2(download_resume_removed, debug, true,
E_SIMPLE2(download_resume_removed, debug,
std::string, api_path, ap, E_FROM_STRING,
std::string, dest_path, dest, E_FROM_STRING
);
E_SIMPLE1(item_timeout, trace, true,
E_SIMPLE1(item_timeout, trace,
std::string, api_path, ap, E_FROM_STRING
);
E_SIMPLE3(download_type_selected, debug, true,
E_SIMPLE3(download_type_selected, debug,
std::string, api_path, ap, E_FROM_STRING,
std::string, source, src, E_FROM_STRING,
download_type, download_type, type, E_FROM_DOWNLOAD_TYPE

View File

@ -39,6 +39,11 @@ class i_provider;
class file_manager final : public i_file_manager, public i_upload_manager {
E_CONSUMER();
private:
static constexpr const std::chrono::seconds queue_wait_secs{
5s,
};
public:
file_manager(app_config &config, i_provider &provider);
@ -72,15 +77,19 @@ private:
void close_timed_out_files();
auto get_open_file_by_handle(std::uint64_t handle) const
[[nodiscard]] auto get_open_file_by_handle(std::uint64_t handle) const
-> std::shared_ptr<i_closeable_open_file>;
auto get_open_file_count(const std::string &api_path) const -> std::size_t;
[[nodiscard]] auto get_open_file_count(const std::string &api_path) const
-> std::size_t;
auto open(const std::string &api_path, bool directory,
const open_file_data &ofd, std::uint64_t &handle,
std::shared_ptr<i_open_file> &file,
std::shared_ptr<i_closeable_open_file> closeable_file) -> api_error;
[[nodiscard]] auto get_stop_requested() const -> bool;
[[nodiscard]] auto open(const std::string &api_path, bool directory,
const open_file_data &ofd, std::uint64_t &handle,
std::shared_ptr<i_open_file> &file,
std::shared_ptr<i_closeable_open_file> closeable_file)
-> api_error;
void queue_upload(const std::string &api_path, const std::string &source_path,
bool no_lock);

View File

@ -78,8 +78,8 @@ private:
stop_type stop_requested_{false};
private:
[[nodiscard]] auto adjust_cache_size(std::uint64_t file_size,
bool shrink) -> api_error;
[[nodiscard]] auto adjust_cache_size(std::uint64_t file_size, bool shrink)
-> api_error;
[[nodiscard]] auto check_start() -> api_error;
@ -88,6 +88,8 @@ private:
void download_range(std::size_t begin_chunk, std::size_t end_chunk,
bool should_reset);
[[nodiscard]] auto get_stop_requested() const -> bool;
void set_modified();
void set_read_state(std::size_t chunk);
@ -111,12 +113,12 @@ public:
return true;
}
[[nodiscard]] auto
native_operation(native_operation_callback callback) -> api_error override;
[[nodiscard]] auto native_operation(native_operation_callback callback)
-> api_error override;
[[nodiscard]] auto
native_operation(std::uint64_t new_file_size,
native_operation_callback callback) -> api_error override;
[[nodiscard]] auto native_operation(std::uint64_t new_file_size,
native_operation_callback callback)
-> api_error override;
void remove(std::uint64_t handle) override;

View File

@ -161,7 +161,7 @@ protected:
void set_source_path(std::string source_path);
void wait_for_io(stop_type &stop_requested);
void wait_for_io(stop_type_callback stop_requested_cb);
public:
void add(std::uint64_t handle, open_file_data ofd) override;
@ -186,17 +186,17 @@ public:
[[nodiscard]] auto get_handles() const -> std::vector<std::uint64_t> override;
[[nodiscard]] auto
get_open_data() -> std::map<std::uint64_t, open_file_data> & override;
[[nodiscard]] auto get_open_data()
-> std::map<std::uint64_t, open_file_data> & override;
[[nodiscard]] auto get_open_data() const
-> const std::map<std::uint64_t, open_file_data> & override;
[[nodiscard]] auto
get_open_data(std::uint64_t handle) -> open_file_data & override;
[[nodiscard]] auto get_open_data(std::uint64_t handle)
-> open_file_data & override;
[[nodiscard]] auto
get_open_data(std::uint64_t handle) const -> const open_file_data & override;
[[nodiscard]] auto get_open_data(std::uint64_t handle) const
-> const open_file_data & override;
[[nodiscard]] auto get_open_file_count() const -> std::size_t override;

View File

@ -44,8 +44,8 @@ public:
ring_buffer_base(const ring_buffer_base &) noexcept = delete;
ring_buffer_base(ring_buffer_base &&) noexcept = delete;
auto operator=(ring_buffer_base &&) noexcept -> ring_buffer_base & = delete;
auto
operator=(const ring_buffer_base &) noexcept -> ring_buffer_base & = delete;
auto operator=(const ring_buffer_base &) noexcept
-> ring_buffer_base & = delete;
public:
static constexpr const auto min_ring_size{5U};
@ -73,6 +73,8 @@ private:
void update_position(std::size_t count, bool is_forward);
[[nodiscard]] auto get_stop_requested() const -> bool;
protected:
[[nodiscard]] auto has_reader_thread() const -> bool {
return reader_thread_ != nullptr;
@ -84,9 +86,9 @@ protected:
[[nodiscard]] virtual auto on_check_start() -> bool = 0;
[[nodiscard]] virtual auto
on_chunk_downloaded(std::size_t chunk,
const data_buffer &buffer) -> api_error = 0;
[[nodiscard]] virtual auto on_chunk_downloaded(std::size_t chunk,
const data_buffer &buffer)
-> api_error = 0;
[[nodiscard]] virtual auto
on_read_chunk(std::size_t chunk, std::size_t read_size,
@ -94,8 +96,8 @@ protected:
std::size_t &bytes_read) -> api_error = 0;
[[nodiscard]] virtual auto
use_buffer(std::size_t chunk,
std::function<api_error(data_buffer &)> func) -> api_error = 0;
use_buffer(std::size_t chunk, std::function<api_error(data_buffer &)> func)
-> api_error = 0;
public:
auto close() -> bool override;
@ -139,9 +141,10 @@ public:
void set_api_path(const std::string &api_path) override;
[[nodiscard]] auto
write(std::uint64_t /* write_offset */, const data_buffer & /* data */,
std::size_t & /* bytes_written */) -> api_error override {
[[nodiscard]] auto write(std::uint64_t /* write_offset */,
const data_buffer & /* data */,
std::size_t & /* bytes_written */)
-> api_error override {
return api_error::not_supported;
}
};

View File

@ -47,8 +47,8 @@ private:
private:
bool cancelled_{false};
api_error error_{api_error::success};
std::unique_ptr<std::thread> thread_;
stop_type stop_requested_{false};
std::unique_ptr<std::thread> thread_;
private:
void upload_thread();

View File

@ -38,7 +38,6 @@ private:
std::unique_ptr<httplib::Server> server_;
std::unique_ptr<std::thread> server_thread_;
std::mutex start_stop_mutex_;
std::atomic<bool> started_ = false;
private:
[[nodiscard]] auto check_authorization(const httplib::Request &req) -> bool;

View File

@ -246,6 +246,22 @@ download_type_from_string(std::string type,
[[nodiscard]] auto download_type_to_string(const download_type &type)
-> std::string;
enum class event_level {
critical,
error,
warn,
info,
debug,
trace,
};
[[nodiscard]] auto
event_level_from_string(std::string level,
event_level default_level = event_level::info)
-> event_level;
[[nodiscard]] auto event_level_to_string(event_level level) -> std::string;
enum class exit_code : std::int32_t {
success = 0,
communication_error = -1,
@ -654,6 +670,18 @@ template <> struct adl_serializer<repertory::download_type> {
value = repertory::download_type_from_string(data.get<std::string>());
}
};
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_TYPES_REPERTORY_HPP_

View File

@ -75,6 +75,8 @@ private:
void frequency_thread(std::function<std::uint32_t()> get_frequency_seconds,
frequency freq);
[[nodiscard]] auto get_stop_requested() const -> bool;
public:
void remove_callback(const std::string &name);

View File

@ -36,7 +36,7 @@ private:
const std::string service_name_;
mutable std::mutex mtx_;
mutable std::condition_variable notify_;
stop_type stop_requested_ = false;
stop_type stop_requested_{false};
std::unique_ptr<std::thread> thread_;
protected:
@ -46,9 +46,7 @@ protected:
return notify_;
}
[[nodiscard]] auto get_stop_requested() const -> bool {
return stop_requested_;
}
[[nodiscard]] auto get_stop_requested() const -> bool;
void notify_all() const;

View File

@ -104,6 +104,8 @@ private:
private:
void task_thread();
[[nodiscard]] auto get_stop_requested() const -> bool;
public:
auto schedule(task item) -> task_ptr;

View File

@ -37,7 +37,7 @@ public:
~timeout() { disable(); }
private:
bool timeout_killed_;
std::atomic<bool> timeout_killed_;
std::unique_ptr<std::thread> timeout_thread_;
std::mutex timeout_mutex_;
std::condition_variable timeout_notify_;

View File

@ -57,6 +57,12 @@ auto get_value(const json &data, const std::string &name, dest &dst,
} // namespace
namespace repertory {
stop_type app_config::stop_requested{false};
auto app_config::get_stop_requested() -> bool { return stop_requested.load(); }
void app_config::set_stop_requested() { stop_requested.store(true); }
app_config::app_config(const provider_type &prov,
std::string_view data_directory)
: prov_(prov),

View File

@ -33,7 +33,7 @@ const curl_comm::write_callback curl_comm::write_data =
auto &info = *reinterpret_cast<read_write_info *>(outstream);
std::copy(buffer, buffer + (size * nitems),
std::back_inserter(info.data));
return info.stop_requested ? 0 : size * nitems;
return info.stop_requested_cb() ? 0 : size * nitems;
});
const curl_comm::write_callback curl_comm::write_headers =
@ -102,8 +102,8 @@ auto curl_comm::reset_curl(CURL *curl_handle) -> CURL * {
return curl_handle;
}
auto curl_comm::create_host_config(const s3_config &cfg,
bool use_s3_path_style) -> host_config {
auto curl_comm::create_host_config(const s3_config &cfg, bool use_s3_path_style)
-> host_config {
host_config host_cfg{};
host_cfg.api_password = cfg.secret_key;
host_cfg.api_user = cfg.access_key;

View File

@ -21,6 +21,7 @@
*/
#include "comm/curl/multi_request.hpp"
#include "app_config.hpp"
#include "utils/utils.hpp"
namespace repertory {
@ -46,7 +47,7 @@ void multi_request::get_result(CURLcode &curl_code, long &http_code) {
auto error = false;
int running_handles = 0;
curl_multi_perform(multi_handle_, &running_handles);
while (not error && (running_handles > 0) && not stop_requested_) {
while (not error && (running_handles > 0) && not get_stop_requested()) {
int ignored{};
curl_multi_wait(multi_handle_, nullptr, 0, timeout_ms, &ignored);
@ -54,7 +55,7 @@ void multi_request::get_result(CURLcode &curl_code, long &http_code) {
error = (ret != CURLM_CALL_MULTI_PERFORM) && (ret != CURLM_OK);
}
if (not stop_requested_) {
if (not get_stop_requested()) {
int remaining_messages = 0;
auto *multi_result =
curl_multi_info_read(multi_handle_, &remaining_messages);
@ -65,4 +66,8 @@ void multi_request::get_result(CURLcode &curl_code, long &http_code) {
}
}
}
auto multi_request::get_stop_requested() const -> bool {
return stop_requested_ || app_config::get_stop_requested();
}
} // namespace repertory

View File

@ -32,7 +32,7 @@
namespace repertory {
// clang-format off
E_SIMPLE2(packet_client_timeout, error, true,
E_SIMPLE2(packet_client_timeout, error,
std::string, event_name, en, E_FROM_STRING,
std::string, message, msg, E_FROM_STRING
);
@ -112,8 +112,8 @@ void packet_client::put_client(std::shared_ptr<client> &cli) {
}
}
auto packet_client::read_packet(client &cli,
packet &response) const -> packet::error_type {
auto packet_client::read_packet(client &cli, packet &response) const
-> packet::error_type {
data_buffer buffer(sizeof(std::uint32_t));
const auto read_buffer = [&]() {
std::uint32_t offset{};
@ -154,8 +154,8 @@ void packet_client::resolve() {
.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) -> packet::error_type {
auto packet_client::send(std::string_view method, std::uint32_t &service_flags)
-> packet::error_type {
packet request;
return send(method, request, service_flags);
}
@ -167,8 +167,8 @@ auto packet_client::send(std::string_view method, packet &request,
}
auto packet_client::send(std::string_view method, packet &request,
packet &response,
std::uint32_t &service_flags) -> packet::error_type {
packet &response, std::uint32_t &service_flags)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
auto success = false;

View File

@ -151,11 +151,11 @@ auto rdb_file_db::count() const -> std::uint64_t {
void rdb_file_db::enumerate_item_list(
std::function<void(const std::vector<i_file_db::file_info> &)> callback,
stop_type &stop_requested) const {
stop_type_callback stop_requested_cb) const {
std::vector<i_file_db::file_info> list;
{
auto iter = create_iterator(file_family_);
for (iter->SeekToFirst(); not stop_requested && iter->Valid();
for (iter->SeekToFirst(); not stop_requested_cb() && iter->Valid();
iter->Next()) {
auto json_data = json::parse(iter->value().ToString());
list.emplace_back(i_file_db::file_info{
@ -175,7 +175,7 @@ void rdb_file_db::enumerate_item_list(
{
auto iter = create_iterator(directory_family_);
for (iter->SeekToFirst(); not stop_requested && iter->Valid();
for (iter->SeekToFirst(); not stop_requested_cb() && iter->Valid();
iter->Next()) {
list.emplace_back(i_file_db::file_info{
iter->key().ToString(),
@ -311,12 +311,12 @@ auto rdb_file_db::get_file_source_path(const std::string &api_path,
return result;
}
auto rdb_file_db::get_item_list(stop_type &stop_requested) const
auto rdb_file_db::get_item_list(stop_type_callback stop_requested_cb) 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(); not stop_requested && iter->Valid();
for (iter->SeekToFirst(); not stop_requested_cb() && iter->Valid();
iter->Next()) {
ret.emplace_back(i_file_db::file_info{
iter->key().ToString(),
@ -328,7 +328,7 @@ auto rdb_file_db::get_item_list(stop_type &stop_requested) const
{
auto iter = create_iterator(file_family_);
for (iter->SeekToFirst(); not stop_requested && iter->Valid();
for (iter->SeekToFirst(); not stop_requested_cb() && iter->Valid();
iter->Next()) {
auto json_data = json::parse(iter->value().ToString());
ret.emplace_back(i_file_db::file_info{

View File

@ -66,11 +66,12 @@ auto rdb_meta_db::create_iterator(rocksdb::ColumnFamilyHandle *family) const
void rdb_meta_db::enumerate_api_path_list(
std::function<void(const std::vector<std::string> &)> callback,
stop_type &stop_requested) const {
stop_type_callback stop_requested_cb) const {
std::vector<std::string> list{};
auto iter = create_iterator(meta_family_);
for (iter->SeekToFirst(); not stop_requested && iter->Valid(); iter->Next()) {
for (iter->SeekToFirst(); not stop_requested_cb() && iter->Valid();
iter->Next()) {
list.push_back(iter->key().ToString());
if (list.size() < 100U) {

View File

@ -135,11 +135,11 @@ auto sqlite_file_db::count() const -> std::uint64_t {
void sqlite_file_db::enumerate_item_list(
std::function<void(const std::vector<i_file_db::file_info> &)> callback,
stop_type &stop_requested) const {
stop_type_callback stop_requested_cb) const {
std::vector<i_file_db::file_info> list;
auto result = utils::db::sqlite::db_select{*db_, file_table}.go();
while (not stop_requested && result.has_row()) {
while (not stop_requested_cb() && result.has_row()) {
std::optional<utils::db::sqlite::db_result::row> row;
if (result.get_row(row) && row.has_value()) {
list.emplace_back(i_file_db::file_info{
@ -309,12 +309,12 @@ auto sqlite_file_db::get_file_source_path(const std::string &api_path,
return api_error::item_not_found;
}
auto sqlite_file_db::get_item_list(stop_type &stop_requested) const
auto sqlite_file_db::get_item_list(stop_type_callback stop_requested_cb) 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 (not stop_requested && result.has_row()) {
while (not stop_requested_cb() && 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{

View File

@ -77,12 +77,12 @@ void sqlite_meta_db::clear() {
void sqlite_meta_db::enumerate_api_path_list(
std::function<void(const std::vector<std::string> &)> callback,
stop_type &stop_requested) const {
stop_type_callback stop_requested_cb) const {
auto result =
utils::db::sqlite::db_select{*db_, table_name}.column("api_path").go();
std::vector<std::string> list{};
while (not stop_requested && result.has_row()) {
while (not stop_requested_cb() && result.has_row()) {
std::optional<utils::db::sqlite::db_result::row> row;
if (result.get_row(row) && row.has_value()) {
list.push_back(row->get_column("api_path").get_value<std::string>());
@ -343,7 +343,7 @@ auto sqlite_meta_db::set_item_meta(const std::string &api_path,
// TODO handle error
}
for (auto &&item : meta) {
for (const auto &item : meta) {
existing_meta[item.first] = item.second;
}

View File

@ -38,14 +38,15 @@ void directory_cache::execute_action(const std::string &api_path,
auto directory_cache::get_directory(std::uint64_t handle)
-> std::shared_ptr<directory_iterator> {
recur_mutex_lock directory_lock(directory_mutex_);
auto it = std::find_if(directory_lookup_.begin(), directory_lookup_.end(),
[handle](auto &&kv) -> bool {
auto &&handles = kv.second.handles;
return std::find(handles.begin(), handles.end(),
handle) != kv.second.handles.end();
});
if (it != directory_lookup_.end()) {
return it->second.iterator;
auto iter =
std::find_if(directory_lookup_.begin(), directory_lookup_.end(),
[handle](auto &&item) -> bool {
auto &&handles = item.second.handles;
return std::find(handles.begin(), handles.end(), handle) !=
item.second.handles.end();
});
if (iter != directory_lookup_.end()) {
return iter->second.iterator;
}
return nullptr;
@ -66,39 +67,20 @@ auto directory_cache::remove_directory(const std::string &api_path)
void directory_cache::remove_directory(std::uint64_t handle) {
recur_mutex_lock directory_lock(directory_mutex_);
auto it = std::find_if(directory_lookup_.begin(), directory_lookup_.end(),
[handle](auto &&kv) -> bool {
auto &&handles = kv.second.handles;
return std::find(handles.begin(), handles.end(),
handle) != kv.second.handles.end();
});
if (it != directory_lookup_.end()) {
utils::collection::remove_element(it->second.handles, handle);
if (it->second.handles.empty()) {
directory_lookup_.erase(it);
}
}
}
void directory_cache::service_function() {
unique_recur_mutex_lock directory_lock(directory_mutex_);
auto lookup = directory_lookup_;
directory_lock.unlock();
for (auto &&kv : lookup) {
if (std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now() - kv.second.last_update) >= 120s) {
directory_lock.lock();
directory_lookup_.erase(kv.first);
directory_lock.unlock();
}
auto iter =
std::find_if(directory_lookup_.begin(), directory_lookup_.end(),
[handle](auto &&item) -> bool {
auto &&handles = item.second.handles;
return std::find(handles.begin(), handles.end(), handle) !=
item.second.handles.end();
});
if (iter == directory_lookup_.end()) {
return;
}
if (not get_stop_requested()) {
unique_mutex_lock shutdown_lock(get_mutex());
if (not get_stop_requested()) {
get_notify().wait_for(shutdown_lock, 15s);
}
utils::collection::remove_element(iter->second.handles, handle);
if (iter->second.handles.empty()) {
directory_lookup_.erase(iter);
}
}

View File

@ -33,70 +33,71 @@ auto directory_iterator::fill_buffer(const remote::file_offset &offset,
-> int {
REPERTORY_USES_FUNCTION_NAME();
if (offset < items_.size()) {
try {
std::string item_name;
struct stat st{};
struct stat *pst = nullptr;
switch (offset) {
case 0: {
item_name = ".";
} break;
if (offset >= items_.size()) {
errno = 120;
return -1;
}
case 1: {
item_name = "..";
} break;
try {
std::string item_name;
struct stat st{};
struct stat *pst = nullptr;
switch (offset) {
case 0: {
item_name = ".";
} break;
default: {
const auto &item = items_[offset];
item_name = utils::path::strip_to_file_name(item.api_path);
populate_stat(item.api_path, item.size, item.meta, item.directory, &st);
pst = &st;
} break;
}
case 1: {
item_name = "..";
} break;
#if FUSE_USE_VERSION >= 30
if (filler_function(buffer, item_name.data(), pst,
static_cast<off_t>(offset + 1),
FUSE_FILL_DIR_PLUS) != 0) {
#else
if (filler_function(buffer, item_name.data(), pst,
static_cast<off_t>(offset + 1)) != 0) {
#endif
errno = ENOMEM;
return -1;
}
} catch (const std::exception &e) {
utils::error::raise_error(function_name, e,
"failed to fill fuse directory buffer");
default: {
const auto &item = items_[offset];
item_name = utils::path::strip_to_file_name(item.api_path);
populate_stat(item.api_path, item.size, item.meta, item.directory, &st);
pst = &st;
} break;
}
return 0;
#if FUSE_USE_VERSION >= 30
if (filler_function(buffer, item_name.data(), pst,
static_cast<off_t>(offset + 1),
FUSE_FILL_DIR_PLUS) != 0)
#else // FUSE_USE_VERSION < 30
if (filler_function(buffer, item_name.data(), pst,
static_cast<off_t>(offset + 1)) != 0)
#endif // FUSE_USE_VERSION >= 30
{
errno = ENOMEM;
return -1;
}
} catch (const std::exception &e) {
utils::error::raise_error(function_name, e,
"failed to fill fuse directory buffer");
}
errno = 120;
return -1;
return 0;
}
#endif // !_WIN32
#endif // !defined(_WIN32)
auto directory_iterator::get(std::size_t offset, std::string &item) -> int {
if (offset < items_.size()) {
item = items_[offset].api_path;
return 0;
if (offset >= items_.size()) {
errno = 120;
return -1;
}
errno = 120;
return -1;
item = items_[offset].api_path;
return 0;
}
auto directory_iterator::get_directory_item(std::size_t offset,
directory_item &di) -> api_error {
if (offset < items_.size()) {
di = items_[offset];
return api_error::success;
if (offset >= items_.size()) {
return api_error::directory_end_of_files;
}
return api_error::directory_end_of_files;
di = items_[offset];
return api_error::success;
}
auto directory_iterator::get_directory_item(const std::string &api_path,
@ -105,22 +106,22 @@ auto directory_iterator::get_directory_item(const std::string &api_path,
std::find_if(items_.begin(), items_.end(), [&](const auto &item) -> bool {
return api_path == item.api_path;
});
if (iter != items_.end()) {
di = *iter;
return api_error::success;
if (iter == items_.end()) {
return api_error::item_not_found;
}
return api_error::item_not_found;
di = *iter;
return api_error::success;
}
auto directory_iterator::get_json(std::size_t offset, json &item) -> int {
if (offset < items_.size()) {
item = json(items_.at(offset));
return 0;
if (offset >= items_.size()) {
errno = 120;
return -1;
}
errno = 120;
return -1;
item = json(items_.at(offset));
return 0;
}
auto directory_iterator::get_next_directory_offset(

View File

@ -632,7 +632,7 @@ auto fuse_base::parse_args(std::vector<std::string> &args) -> int {
}
const auto option_parts = utils::string::split(options, ',', true);
for (auto &&option : option_parts) {
for (const auto &option : option_parts) {
if (option.find("gid") == 0) {
const auto parts = utils::string::split(option, '=', true);
if (parts.size() == 2u) {

View File

@ -246,48 +246,59 @@ auto fuse_drive::create_impl(std::string api_path, mode_t mode,
return api_error::success;
}
void fuse_drive::stop_all() {
REPERTORY_USES_FUNCTION_NAME();
mutex_lock lock(stop_all_mtx_);
auto future = std::async(std::launch::async, [this]() {
remote_server_.reset();
if (server_) {
server_->stop();
}
polling::instance().stop();
if (eviction_) {
eviction_->stop();
}
if (fm_) {
fm_->stop();
}
provider_.stop();
directory_cache_.reset();
eviction_.reset();
server_.reset();
fm_.reset();
});
if (future.wait_for(30s) == std::future_status::timeout) {
app_config::set_stop_requested();
future.wait();
}
if (not lock_data_.set_mount_state(false, "", -1)) {
utils::error::raise_error(function_name, "failed to set mount state");
}
}
void fuse_drive::destroy_impl(void *ptr) {
REPERTORY_USES_FUNCTION_NAME();
event_system::instance().raise<drive_unmount_pending>(get_mount_location());
remote_server_.reset();
if (server_) {
server_->stop();
}
polling::instance().stop();
if (eviction_) {
eviction_->stop();
}
if (fm_) {
fm_->stop();
}
provider_.stop();
if (directory_cache_) {
directory_cache_->stop();
}
directory_cache_.reset();
eviction_.reset();
server_.reset();
fm_.reset();
event_system::instance().raise<drive_unmounted>(get_mount_location());
stop_all();
config_.save();
if (not lock_data_.set_mount_state(false, "", -1)) {
utils::error::raise_error(function_name, "failed to set mount state");
}
fuse_base::destroy_impl(ptr);
event_system::instance().raise<drive_unmounted>(get_mount_location());
}
auto fuse_drive::fallocate_impl(std::string /*api_path*/, int mode,
@ -486,28 +497,16 @@ auto fuse_drive::getattr_impl(std::string api_path, struct stat *unix_st)
return res;
}
auto found = false;
directory_cache_->execute_action(parent, [&](directory_iterator &iter) {
directory_item dir_item{};
found = (iter.get_directory_item(api_path, dir_item) == api_error::success);
if (found) {
fuse_drive_base::populate_stat(api_path, dir_item.size, dir_item.meta,
dir_item.directory, provider_, unix_st);
}
});
if (not found) {
api_meta_map meta{};
res = provider_.get_item_meta(api_path, meta);
if (res != api_error::success) {
return res;
}
fuse_drive_base::populate_stat(
api_path, utils::string::to_uint64(meta[META_SIZE]), meta,
utils::string::to_bool(meta[META_DIRECTORY]), provider_, unix_st);
api_meta_map meta{};
res = provider_.get_item_meta(api_path, meta);
if (res != api_error::success) {
return res;
}
fuse_drive_base::populate_stat(
api_path, utils::string::to_uint64(meta[META_SIZE]), meta,
utils::string::to_bool(meta[META_DIRECTORY]), provider_, unix_st);
return api_error::success;
}
@ -568,25 +567,24 @@ void *fuse_drive::init_impl(struct fuse_conn_info *conn) {
auto *ret = fuse_drive_base::init_impl(conn);
#endif
if (console_enabled_) {
console_consumer_ =
std::make_unique<console_consumer>(config_.get_event_level());
}
logging_consumer_ = std::make_unique<logging_consumer>(
config_.get_event_level(), config_.get_log_directory());
event_system::instance().start();
was_mounted_ = true;
fm_ = std::make_unique<file_manager>(config_, provider_);
server_ = std::make_unique<full_server>(config_, provider_, *fm_);
if (not provider_.is_read_only()) {
eviction_ = std::make_unique<eviction>(provider_, config_, *fm_);
}
directory_cache_ = std::make_unique<directory_cache>();
try {
directory_cache_->start();
if (console_enabled_) {
console_consumer_ =
std::make_unique<console_consumer>(config_.get_event_level());
}
logging_consumer_ = std::make_unique<logging_consumer>(
config_.get_event_level(), config_.get_log_directory());
event_system::instance().start();
was_mounted_ = true;
fm_ = std::make_unique<file_manager>(config_, provider_);
server_ = std::make_unique<full_server>(config_, provider_, *fm_);
if (not provider_.is_read_only()) {
eviction_ = std::make_unique<eviction>(provider_, config_, *fm_);
}
directory_cache_ = std::make_unique<directory_cache>();
server_->start();
if (not provider_.start(
@ -607,12 +605,12 @@ void *fuse_drive::init_impl(struct fuse_conn_info *conn) {
config_, *this, get_mount_location());
}
polling::instance().start(&config_);
if (not lock_data_.set_mount_state(true, get_mount_location(), getpid())) {
utils::error::raise_error(function_name, "failed to set mount state");
}
polling::instance().start(&config_);
event_system::instance().raise<drive_mounted>(get_mount_location());
} catch (const std::exception &e) {
utils::error::raise_error(function_name, e, "exception during fuse init");
@ -892,19 +890,7 @@ auto fuse_drive::getxattr_common(std::string api_path, const char *name,
}
api_meta_map meta;
auto found{false};
directory_cache_->execute_action(
utils::path::get_parent_api_path(api_path),
[&](directory_iterator &iterator) {
directory_item dir_item{};
found = (iterator.get_directory_item(api_path, dir_item) ==
api_error::success);
if (found) {
meta = dir_item.meta;
}
});
res = found ? api_error::success : provider_.get_item_meta(api_path, meta);
res = provider_.get_item_meta(api_path, meta);
if (res != api_error::success) {
return res;
}
@ -958,7 +944,7 @@ auto fuse_drive::listxattr_impl(std::string api_path, char *buffer, size_t size,
api_meta_map meta;
res = provider_.get_item_meta(api_path, meta);
if (res == api_error::success) {
for (auto &&meta_item : meta) {
for (const auto &meta_item : meta) {
if (utils::collection::excludes(META_USED_NAMES, meta_item.first)) {
auto attribute_name = meta_item.first;
#if defined(__APPLE__)

View File

@ -41,13 +41,13 @@ namespace repertory::remote_fuse {
#define RAISE_REMOTE_FUSE_SERVER_EVENT(func, file, ret) \
if (config_.get_enable_drive_events() && \
(((config_.get_event_level() >= remote_fuse_server_event::level) && \
(ret < 0)) || \
((ret) < 0)) || \
(config_.get_event_level() >= event_level::trace))) \
event_system::instance().raise<remote_fuse_server_event>(std::string{func}, \
file, ret)
// clang-format off
E_SIMPLE3(remote_fuse_server_event, debug, true,
E_SIMPLE3(remote_fuse_server_event, debug,
std::string, function, func, E_FROM_STRING,
std::string, api_path, ap, E_FROM_STRING,
packet::error_type, result, res, E_FROM_INT32
@ -208,8 +208,8 @@ auto remote_server::fuse_access(const char *path, const std::int32_t &mask)
return ret;
}
auto remote_server::fuse_chflags(const char *path,
std::uint32_t flags) -> packet::error_type {
auto remote_server::fuse_chflags(const char *path, std::uint32_t flags)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto api_path = utils::path::create_api_path(path);
@ -321,9 +321,10 @@ length); ret = ((res < 0) ? -errno : 0); #endif
return ret;
}*/
auto remote_server::fuse_fgetattr(
const char *path, remote::stat &r_stat, bool &directory,
const remote::file_handle &handle) -> packet::error_type {
auto remote_server::fuse_fgetattr(const char *path, remote::stat &r_stat,
bool &directory,
const remote::file_handle &handle)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
r_stat = {};
@ -333,7 +334,7 @@ auto remote_server::fuse_fgetattr(
auto res = has_open_info(static_cast<native_handle>(handle), EBADF);
if (res == 0) {
directory = utils::file::directory(file_path).exists();
struct stat64 unix_st {};
struct stat64 unix_st{};
res = fstat64(static_cast<native_handle>(handle), &unix_st);
if (res == 0) {
populate_stat(unix_st, r_stat);
@ -345,9 +346,10 @@ auto remote_server::fuse_fgetattr(
return ret;
}
auto remote_server::fuse_fsetattr_x(
const char *path, const remote::setattr_x &attr,
const remote::file_handle &handle) -> packet::error_type {
auto remote_server::fuse_fsetattr_x(const char *path,
const remote::setattr_x &attr,
const remote::file_handle &handle)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto api_path = utils::path::create_api_path(path);
@ -463,9 +465,10 @@ auto remote_server::fuse_fsync(const char *path, const std::int32_t &datasync,
return ret;
}
auto remote_server::fuse_ftruncate(
const char *path, const remote::file_offset &size,
const remote::file_handle &handle) -> packet::error_type {
auto remote_server::fuse_ftruncate(const char *path,
const remote::file_offset &size,
const remote::file_handle &handle)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto file_path = construct_path(path);
@ -493,7 +496,7 @@ auto remote_server::fuse_getattr(const char *path, remote::stat &r_stat,
directory = utils::file::directory(file_path).exists();
struct stat64 unix_st {};
struct stat64 unix_st{};
auto res = stat64(file_path.c_str(), &unix_st);
if (res == 0) {
populate_stat(unix_st, r_stat);
@ -558,9 +561,10 @@ STATUS_NOT_IMPLEMENTED; #endif RAISE_REMOTE_FUSE_SERVER_EVENT(function_name,
file_path, ret); return ret;
}*/
auto remote_server::fuse_getxtimes(
const char *path, remote::file_time &bkuptime,
remote::file_time &crtime) -> packet::error_type {
auto remote_server::fuse_getxtimes(const char *path,
remote::file_time &bkuptime,
remote::file_time &crtime)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto api_path = utils::path::create_api_path(path);
@ -665,10 +669,11 @@ auto remote_server::fuse_opendir(const char *path, remote::file_handle &handle)
return ret;
}
auto remote_server::fuse_read(
const char *path, char *buffer, const remote::file_size &read_size,
const remote::file_offset &read_offset,
const remote::file_handle &handle) -> packet::error_type {
auto remote_server::fuse_read(const char *path, char *buffer,
const remote::file_size &read_size,
const remote::file_offset &read_offset,
const remote::file_handle &handle)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto file_path = construct_path(path);
@ -689,8 +694,8 @@ auto remote_server::fuse_read(
return static_cast<packet::error_type>(ret);
}
auto remote_server::fuse_rename(const char *from,
const char *to) -> packet::error_type {
auto remote_server::fuse_rename(const char *from, const char *to)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto from_path = utils::path::combine(mount_location_, {from});
@ -728,8 +733,9 @@ auto remote_server::fuse_readdir(const char *path,
return ret;
}
auto remote_server::fuse_release(
const char *path, const remote::file_handle &handle) -> packet::error_type {
auto remote_server::fuse_release(const char *path,
const remote::file_handle &handle)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
packet::error_type ret = 0;
@ -746,8 +752,9 @@ auto remote_server::fuse_release(
return ret;
}
auto remote_server::fuse_releasedir(
const char *path, const remote::file_handle &handle) -> packet::error_type {
auto remote_server::fuse_releasedir(const char *path,
const remote::file_handle &handle)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto file_path = construct_path(path);
@ -792,8 +799,9 @@ auto remote_server::fuse_setattr_x(const char *path, remote::setattr_x &attr)
return ret;
}
auto remote_server::fuse_setbkuptime(
const char *path, const remote::file_time &bkuptime) -> packet::error_type {
auto remote_server::fuse_setbkuptime(const char *path,
const remote::file_time &bkuptime)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto api_path = utils::path::create_api_path(path);
@ -812,8 +820,9 @@ auto remote_server::fuse_setbkuptime(
return ret;
}
auto remote_server::fuse_setchgtime(
const char *path, const remote::file_time &chgtime) -> packet::error_type {
auto remote_server::fuse_setchgtime(const char *path,
const remote::file_time &chgtime)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto api_path = utils::path::create_api_path(path);
@ -832,8 +841,9 @@ auto remote_server::fuse_setchgtime(
return ret;
}
auto remote_server::fuse_setcrtime(
const char *path, const remote::file_time &crtime) -> packet::error_type {
auto remote_server::fuse_setcrtime(const char *path,
const remote::file_time &crtime)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto api_path = utils::path::create_api_path(path);
@ -924,8 +934,9 @@ auto remote_server::fuse_statfs_x(const char *path, std::uint64_t bsize,
return 0;
}
auto remote_server::fuse_truncate(
const char *path, const remote::file_offset &size) -> packet::error_type {
auto remote_server::fuse_truncate(const char *path,
const remote::file_offset &size)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto file_path = construct_path(path);
@ -946,8 +957,8 @@ auto remote_server::fuse_unlink(const char *path) -> packet::error_type {
}
auto remote_server::fuse_utimens(const char *path, const remote::file_time *tv,
std::uint64_t op0,
std::uint64_t op1) -> packet::error_type {
std::uint64_t op0, std::uint64_t op1)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto file_path = construct_path(path);
@ -974,10 +985,11 @@ auto remote_server::fuse_utimens(const char *path, const remote::file_time *tv,
return ret;
}
auto remote_server::fuse_write(
const char *path, const char *buffer, const remote::file_size &write_size,
const remote::file_offset &write_offset,
const remote::file_handle &handle) -> packet::error_type {
auto remote_server::fuse_write(const char *path, const char *buffer,
const remote::file_size &write_size,
const remote::file_offset &write_offset,
const remote::file_handle &handle)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto file_path = construct_path(path);
@ -1007,8 +1019,8 @@ auto remote_server::fuse_write_base64(
}
// WinFSP Layer
auto remote_server::winfsp_can_delete(PVOID file_desc,
PWSTR file_name) -> packet::error_type {
auto remote_server::winfsp_can_delete(PVOID file_desc, PWSTR file_name)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto relative_path = utils::string::to_utf8(file_name);
@ -1033,8 +1045,8 @@ auto remote_server::winfsp_can_delete(PVOID file_desc,
}
auto remote_server::winfsp_cleanup(PVOID /*file_desc*/, PWSTR file_name,
UINT32 flags,
BOOLEAN &was_deleted) -> packet::error_type {
UINT32 flags, BOOLEAN &was_deleted)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto relative_path = utils::string::to_utf8(file_name);
@ -1111,8 +1123,8 @@ auto remote_server::winfsp_create(PWSTR file_name, UINT32 create_options,
UINT32 granted_access, UINT32 attributes,
UINT64 /*allocation_size*/, PVOID *file_desc,
remote::file_info *file_info,
std::string &normalized_name,
BOOLEAN &exists) -> packet::error_type {
std::string &normalized_name, BOOLEAN &exists)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto relative_path = utils::string::to_utf8(file_name);
@ -1184,8 +1196,9 @@ auto remote_server::winfsp_flush(PVOID file_desc, remote::file_info *file_info)
return ret;
}
auto remote_server::winfsp_get_file_info(
PVOID file_desc, remote::file_info *file_info) -> packet::error_type {
auto remote_server::winfsp_get_file_info(PVOID file_desc,
remote::file_info *file_info)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto handle = reinterpret_cast<remote::file_handle>(file_desc);
@ -1228,9 +1241,10 @@ auto remote_server::winfsp_get_security_by_name(
return ret;
}
auto remote_server::winfsp_get_volume_info(
UINT64 &total_size, UINT64 &free_size,
std::string &volume_label) -> packet::error_type {
auto remote_server::winfsp_get_volume_info(UINT64 &total_size,
UINT64 &free_size,
std::string &volume_label)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
drive_.get_volume_info(total_size, free_size, volume_label);
@ -1247,10 +1261,11 @@ auto remote_server::winfsp_mounted(const std::wstring &location)
return STATUS_SUCCESS;
}
auto remote_server::winfsp_open(
PWSTR file_name, UINT32 create_options, UINT32 granted_access,
PVOID *file_desc, remote::file_info *file_info,
std::string &normalized_name) -> packet::error_type {
auto remote_server::winfsp_open(PWSTR file_name, UINT32 create_options,
UINT32 granted_access, PVOID *file_desc,
remote::file_info *file_info,
std::string &normalized_name)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto relative_path = utils::string::to_utf8(file_name);
@ -1291,10 +1306,11 @@ auto remote_server::winfsp_open(
return ret;
}
auto remote_server::winfsp_overwrite(
PVOID file_desc, UINT32 attributes, BOOLEAN replace_attributes,
UINT64 /*allocation_size*/,
remote::file_info *file_info) -> packet::error_type {
auto remote_server::winfsp_overwrite(PVOID file_desc, UINT32 attributes,
BOOLEAN replace_attributes,
UINT64 /*allocation_size*/,
remote::file_info *file_info)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto handle = reinterpret_cast<remote::file_handle>(file_desc);
@ -1410,9 +1426,10 @@ auto remote_server::winfsp_read_directory(PVOID file_desc, PWSTR /*pattern*/,
return ret;
}
auto remote_server::winfsp_rename(
PVOID /*file_desc*/, PWSTR file_name, PWSTR new_file_name,
BOOLEAN replace_if_exists) -> packet::error_type {
auto remote_server::winfsp_rename(PVOID /*file_desc*/, PWSTR file_name,
PWSTR new_file_name,
BOOLEAN replace_if_exists)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto relative_path = utils::string::to_utf8(file_name);
@ -1506,9 +1523,10 @@ auto remote_server::winfsp_set_basic_info(
return ret;
}
auto remote_server::winfsp_set_file_size(
PVOID file_desc, UINT64 new_size, BOOLEAN set_allocation_size,
remote::file_info *file_info) -> packet::error_type {
auto remote_server::winfsp_set_file_size(PVOID file_desc, UINT64 new_size,
BOOLEAN set_allocation_size,
remote::file_info *file_info)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto handle = reinterpret_cast<remote::file_handle>(file_desc);
@ -1544,10 +1562,12 @@ auto remote_server::winfsp_unmounted(const std::wstring &location)
return STATUS_SUCCESS;
}
auto remote_server::winfsp_write(
PVOID file_desc, PVOID buffer, UINT64 offset, UINT32 length,
BOOLEAN write_to_end, BOOLEAN constrained_io, PUINT32 bytes_transferred,
remote::file_info *file_info) -> packet::error_type {
auto remote_server::winfsp_write(PVOID file_desc, PVOID buffer, UINT64 offset,
UINT32 length, BOOLEAN write_to_end,
BOOLEAN constrained_io,
PUINT32 bytes_transferred,
remote::file_info *file_info)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
*bytes_transferred = 0;
@ -1595,8 +1615,9 @@ auto remote_server::winfsp_write(
return ret;
}
auto remote_server::json_create_directory_snapshot(
const std::string &path, json &json_data) -> packet::error_type {
auto remote_server::json_create_directory_snapshot(const std::string &path,
json &json_data)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto api_path = utils::path::create_api_path(path);
@ -1655,8 +1676,8 @@ auto remote_server::json_read_directory_snapshot(
}
auto remote_server::json_release_directory_snapshot(
const std::string &path,
const remote::file_handle &handle) -> packet::error_type {
const std::string &path, const remote::file_handle &handle)
-> packet::error_type {
REPERTORY_USES_FUNCTION_NAME();
const auto file_path = construct_path(path);

View File

@ -65,7 +65,7 @@ void remote_open_file_table::close_all(const std::string &client_id) {
});
lock.unlock();
for (auto &&handle : compat_handles) {
for (const auto &handle : compat_handles) {
#if defined(_WIN32)
_close(static_cast<int>(handle));
#else
@ -74,7 +74,7 @@ void remote_open_file_table::close_all(const std::string &client_id) {
remove_compat_open_info(handle);
}
for (auto &&handle : handles) {
for (const auto &handle : handles) {
#if defined(_WIN32)
::CloseHandle(handle);
#else // !defined(_WIN32)
@ -85,14 +85,14 @@ void remote_open_file_table::close_all(const std::string &client_id) {
std::vector<std::uint64_t> dirs;
lock.lock();
for (auto &&kv : directory_lookup_) {
for (const auto &kv : directory_lookup_) {
if (kv.first == client_id) {
dirs.insert(dirs.end(), kv.second.begin(), kv.second.end());
}
}
lock.unlock();
for (auto &&dir : dirs) {
for (const auto &dir : dirs) {
remove_directory(client_id, dir);
}
}
@ -185,11 +185,11 @@ void remote_open_file_table::remove_all(const std::string &file_path) {
});
lock.unlock();
for (auto &&handle : compat_open_list) {
for (const auto &handle : compat_open_list) {
remove_compat_open_info(handle);
}
for (auto &&handle : open_list) {
for (const auto &handle : open_list) {
remove_open_info(handle);
}
}
@ -262,7 +262,7 @@ void remote_open_file_table::remove_and_close_all(const native_handle &handle) {
auto op_info = *file_lookup_.at(handle_lookup_.at(handle));
lock.unlock();
for (auto &&open_handle : op_info.handles) {
for (const auto &open_handle : op_info.handles) {
#if defined(_WIN32)
::CloseHandle(open_handle);
#else // !defined(_WIN32)

View File

@ -33,13 +33,13 @@ namespace repertory::remote_winfsp {
#define RAISE_REMOTE_WINFSP_CLIENT_EVENT(func, file, ret) \
if (config_.get_enable_drive_events() && \
(((config_.get_event_level() >= remote_winfsp_client_event::level) && \
(ret != STATUS_SUCCESS)) || \
((ret) != STATUS_SUCCESS)) || \
(config_.get_event_level() >= event_level::trace))) \
event_system::instance().raise<remote_winfsp_client_event>( \
std::string{func}, file, ret)
// clang-format off
E_SIMPLE3(remote_winfsp_client_event, debug, true,
E_SIMPLE3(remote_winfsp_client_event, debug,
std::string, function, func, E_FROM_STRING,
std::string, api_path, ap, E_FROM_STRING,
packet::error_type, result, res, E_FROM_INT32

View File

@ -47,13 +47,13 @@ namespace repertory::remote_winfsp {
#define RAISE_REMOTE_WINFSP_SERVER_EVENT(func, file, ret) \
if (config_.get_enable_drive_events() && \
(((config_.get_event_level() >= remote_winfsp_server_event::level) && \
(ret != STATUS_SUCCESS)) || \
((ret) != STATUS_SUCCESS)) || \
(config_.get_event_level() >= event_level::trace))) \
event_system::instance().raise<remote_winfsp_server_event>( \
std::string{func}, file, ret)
// clang-format off
E_SIMPLE3(remote_winfsp_server_event, debug, true,
E_SIMPLE3(remote_winfsp_server_event, debug,
std::string, function, FUNC, E_FROM_STRING,
std::string, api_path, AP, E_FROM_STRING,
packet::error_type, result, RES, E_FROM_INT32

View File

@ -238,7 +238,7 @@ auto remote_winfsp_drive::mount(const std::vector<std::string> &drive_args)
auto force_no_console = utils::collection::includes(drive_args, "-nc");
auto enable_console = false;
for (auto &&arg : drive_args) {
for (const auto &arg : drive_args) {
if (arg == "-f") {
if (not force_no_console) {
enable_console = true;
@ -352,7 +352,7 @@ auto remote_winfsp_drive::ReadDirectory(PVOID /*file_node*/, PVOID file_desc,
directory_buffer, static_cast<BOOLEAN>(nullptr == marker),
&ret)) {
auto item_found = false;
for (auto &&item : item_list) {
for (const auto &item : item_list) {
auto item_path = item["path"].get<std::string>();
auto display_name = utils::string::from_utf8(
utils::path::strip_to_file_name(item_path));

View File

@ -39,15 +39,20 @@
#include "utils/polling.hpp"
#include "utils/string.hpp"
#include "utils/time.hpp"
#include "utils/timeout.hpp"
#include "utils/utils.hpp"
namespace repertory {
// clang-format off
E_SIMPLE3(winfsp_event, debug, true,
E_SIMPLE3(winfsp_event, debug,
std::string, function, func, E_FROM_STRING,
std::string, api_path, ap, E_FROM_STRING,
NTSTATUS, result, res, E_FROM_INT32
);
E_SIMPLE(drive_stop_begin, info);
E_SIMPLE(drive_stop_end, info);
E_SIMPLE(drive_stop_timed_out, info);
// clang-format on
#define RAISE_WINFSP_EVENT(func, file, ret) \
@ -100,7 +105,9 @@ auto winfsp_drive::winfsp_service::OnStart(ULONG /*Argc*/, PWSTR * /*Argv*/)
((mount_location.size() == 3U) && (mount_location[2U] == '\\'))) &&
(mount_location[1U] == ':');
auto ret = drive_letter ? STATUS_DEVICE_BUSY : STATUS_NOT_SUPPORTED;
auto ret{
drive_letter ? STATUS_DEVICE_BUSY : STATUS_NOT_SUPPORTED,
};
if ((drive_letter && not utils::file::directory(mount_location).exists())) {
auto unicode_mount_location = utils::string::from_utf8(mount_location);
host_.SetFileSystemName(unicode_mount_location.data());
@ -116,23 +123,37 @@ auto winfsp_drive::winfsp_service::OnStart(ULONG /*Argc*/, PWSTR * /*Argv*/)
<< mount_location << std::endl;
}
if (ret != STATUS_SUCCESS) {
if (not lock_.set_mount_state(false, "", -1)) {
utils::error::raise_error(function_name, ret,
"failed to set mount state");
}
event_system::instance().raise<drive_mount_failed>(mount_location,
std::to_string(ret));
if (ret == STATUS_SUCCESS) {
return ret;
}
if (not lock_.set_mount_state(false, "", -1)) {
utils::error::raise_error(function_name, ret, "failed to set mount state");
}
event_system::instance().raise<drive_mount_failed>(mount_location,
std::to_string(ret));
return ret;
}
auto winfsp_drive::winfsp_service::OnStop() -> NTSTATUS {
REPERTORY_USES_FUNCTION_NAME();
event_system::instance().raise<drive_stop_begin>();
timeout stop_timeout(
[]() {
event_system::instance().raise<drive_stop_timed_out>();
app_config::set_stop_requested();
},
30s);
host_.Unmount();
stop_timeout.disable();
event_system::instance().raise<drive_stop_end>();
if (not lock_.set_mount_state(false, "", -1)) {
utils::error::raise_error(function_name, "failed to set mount state");
}
@ -583,7 +604,7 @@ auto winfsp_drive::mount(const std::vector<std::string> &drive_args) -> int {
auto force_no_console = utils::collection::includes(drive_args, "-nc");
auto enable_console = false;
for (auto &&arg : drive_args) {
for (const auto &arg : drive_args) {
if (arg == "-f") {
if (not force_no_console) {
enable_console = true;
@ -605,28 +626,30 @@ auto winfsp_drive::mount(const std::vector<std::string> &drive_args) -> int {
event_system::instance().raise<drive_mount_result>(std::to_string(ret));
event_system::instance().stop();
cons.reset();
return static_cast<int>(ret);
}
auto winfsp_drive::Mounted(PVOID host) -> NTSTATUS {
REPERTORY_USES_FUNCTION_NAME();
auto ret{STATUS_SUCCESS};
if (not utils::file::change_to_process_directory()) {
return static_cast<NTSTATUS>(utils::get_last_error_code());
}
auto *file_system_host{
reinterpret_cast<FileSystemHost *>(host),
};
fm_ = std::make_unique<file_manager>(config_, provider_);
server_ = std::make_unique<full_server>(config_, provider_, *fm_);
if (not provider_.is_read_only()) {
eviction_ = std::make_unique<eviction>(provider_, config_, *fm_);
}
try {
if (not utils::file::change_to_process_directory()) {
return static_cast<NTSTATUS>(utils::get_last_error_code());
}
auto *file_system_host{
reinterpret_cast<FileSystemHost *>(host),
};
fm_ = std::make_unique<file_manager>(config_, provider_);
server_ = std::make_unique<full_server>(config_, provider_, *fm_);
if (not provider_.is_read_only()) {
eviction_ = std::make_unique<eviction>(provider_, config_, *fm_);
}
server_->start();
if (not provider_.start(
[this](bool directory, api_file &file) -> api_error {
return provider_meta_handler(provider_, directory, file);
@ -646,30 +669,21 @@ auto winfsp_drive::Mounted(PVOID host) -> NTSTATUS {
config_, *this, mount_location);
}
polling::instance().start(&config_);
if (not lock_.set_mount_state(true, mount_location,
::GetCurrentProcessId())) {
utils::error::raise_error(function_name, "failed to set mount state");
}
polling::instance().start(&config_);
event_system::instance().raise<drive_mounted>(mount_location);
return STATUS_SUCCESS;
} catch (const std::exception &e) {
utils::error::raise_error(function_name, e, "exception occurred");
if (remote_server_) {
remote_server_.reset();
}
server_->stop();
polling::instance().stop();
if (eviction_) {
eviction_->stop();
}
fm_->stop();
provider_.stop();
ret = STATUS_INTERNAL_ERROR;
}
return ret;
stop_all();
return STATUS_INTERNAL_ERROR;
}
auto winfsp_drive::Open(PWSTR file_name, UINT32 create_options,
@ -1156,29 +1170,53 @@ auto winfsp_drive::SetFileSize(PVOID /*file_node*/, PVOID file_desc,
}));
}
void winfsp_drive::stop_all() {
REPERTORY_USES_FUNCTION_NAME();
mutex_lock lock(stop_all_mtx_);
auto future = std::async(std::launch::async, [this]() {
remote_server_.reset();
if (server_) {
server_->stop();
}
polling::instance().stop();
if (eviction_) {
eviction_->stop();
}
if (fm_) {
fm_->stop();
}
provider_.stop();
eviction_.reset();
fm_.reset();
server_.reset();
});
if (future.wait_for(30s) == std::future_status::timeout) {
app_config::set_stop_requested();
future.wait();
}
if (not lock_.set_mount_state(false, "", -1)) {
utils::error::raise_error(function_name, "failed to set mount state");
}
}
VOID winfsp_drive::Unmounted(PVOID host) {
REPERTORY_USES_FUNCTION_NAME();
auto *file_system_host = reinterpret_cast<FileSystemHost *>(host);
auto mount_location = parse_mount_location(file_system_host->MountPoint());
event_system::instance().raise<drive_unmount_pending>(mount_location);
if (remote_server_) {
remote_server_.reset();
}
server_->stop();
polling::instance().stop();
if (eviction_) {
eviction_->stop();
}
fm_->stop();
provider_.stop();
server_.reset();
fm_.reset();
eviction_.reset();
if (not lock_.set_mount_state(false, "", -1)) {
utils::error::raise_error(function_name, "failed to set mount state");
}
stop_all();
event_system::instance().raise<drive_unmounted>(mount_location);
config_.save();

View File

@ -1,75 +0,0 @@
/*
Copyright <2018-2025> <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 "events/event.hpp"
#include "utils/string.hpp"
namespace repertory {
auto event_level_from_string(std::string level,
event_level default_level) -> event_level {
level = utils::string::to_lower(level);
if (level == "critical" || level == "event_level::critical") {
return event_level::critical;
}
if (level == "debug" || level == "event_level::debug") {
return event_level::debug;
}
if (level == "warn" || level == "event_level::warn") {
return event_level::warn;
}
if (level == "info" || level == "event_level::info") {
return event_level::info;
}
if (level == "error" || level == "event_level::error") {
return event_level::error;
}
if (level == "trace" || level == "event_level::trace") {
return event_level::trace;
}
return default_level;
}
auto event_level_to_string(event_level level) -> std::string {
switch (level) {
case event_level::critical:
return "critical";
case event_level::debug:
return "debug";
case event_level::error:
return "error";
case event_level::info:
return "info";
case event_level::warn:
return "warn";
case event_level::trace:
return "trace";
default:
return "info";
}
}
} // namespace repertory

View File

@ -29,12 +29,12 @@
namespace repertory {
// clang-format off
E_SIMPLE2(invalid_cache_size, warn, true,
E_SIMPLE2(invalid_cache_size, warn,
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,
E_SIMPLE2(max_cache_size_reached, warn,
std::uint64_t, cache_size, sz, E_FROM_UINT64,
std::uint64_t, max_cache_size, max, E_FROM_UINT64
);
@ -42,32 +42,44 @@ E_SIMPLE2(max_cache_size_reached, warn, true,
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) {
notify_.notify_all();
return api_error::cache_not_initialized;
}
if (size == 0U) {
notify_.notify_all();
return api_error::success;
}
auto last_cache_size{cache_size_};
cache_size_ += size;
auto max_cache_size = cfg_->get_max_cache_size_bytes();
auto max_cache_size{cfg_->get_max_cache_size_bytes()};
auto cache_dir = utils::file::directory{cfg_->get_cache_directory()};
while (not stop_requested_ && cache_size_ > max_cache_size &&
auto cache_dir{
utils::file::directory{cfg_->get_cache_directory()},
};
while (not get_stop_requested() && cache_size_ > max_cache_size &&
cache_dir.count() > 1U) {
event_system::instance().raise<max_cache_size_reached>(cache_size_,
max_cache_size);
notify_.wait(lock);
if (last_cache_size != cache_size_) {
event_system::instance().raise<max_cache_size_reached>(cache_size_,
max_cache_size);
last_cache_size = cache_size_;
}
notify_.wait_for(lock, cache_wait_secs);
}
notify_.notify_all();
return api_error::success;
return get_stop_requested() ? api_error::error : api_error::success;
}
auto cache_size_mgr::get_stop_requested() const -> bool {
return stop_requested_ || app_config::get_stop_requested();
}
void cache_size_mgr::initialize(app_config *cfg) {
@ -80,7 +92,9 @@ void cache_size_mgr::initialize(app_config *cfg) {
stop_requested_ = false;
auto cache_dir = utils::file::directory{cfg_->get_cache_directory()};
auto cache_dir{
utils::file::directory{cfg_->get_cache_directory()},
};
if (not cache_dir.create_directory()) {
throw startup_exception(fmt::format("failed to create cache directory|{}",
cache_dir.get_path()));

View File

@ -287,6 +287,10 @@ auto file_manager::get_open_handle_count() const -> std::size_t {
});
}
auto file_manager::get_stop_requested() const -> bool {
return stop_requested_ || app_config::get_stop_requested();
}
auto file_manager::get_stored_downloads() const
-> std::vector<i_file_mgr_db::resume_entry> {
REPERTORY_USES_FUNCTION_NAME();
@ -1023,7 +1027,7 @@ void file_manager::upload_completed(const file_upload_completed &evt) {
evt.get_api_path(), evt.get_source(), err);
queue_upload(evt.get_api_path(), evt.get_source(), true);
upload_notify_.wait_for(upload_lock, 5s);
upload_notify_.wait_for(upload_lock, queue_wait_secs);
}
}
}
@ -1034,10 +1038,10 @@ void file_manager::upload_completed(const file_upload_completed &evt) {
void file_manager::upload_handler() {
REPERTORY_USES_FUNCTION_NAME();
while (not stop_requested_) {
while (not get_stop_requested()) {
auto should_wait{true};
unique_mutex_lock upload_lock(upload_mtx_);
if (stop_requested_) {
if (get_stop_requested()) {
upload_notify_.notify_all();
continue;
}
@ -1087,7 +1091,7 @@ void file_manager::upload_handler() {
}
if (should_wait) {
upload_notify_.wait_for(upload_lock, 5s);
upload_notify_.wait_for(upload_lock, queue_wait_secs);
}
upload_notify_.notify_all();

View File

@ -118,8 +118,8 @@ open_file::open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
open_file::~open_file() { close(); }
auto open_file::adjust_cache_size(std::uint64_t file_size,
bool shrink) -> api_error {
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()) {
@ -398,11 +398,15 @@ auto open_file::get_read_state(std::size_t chunk) const -> bool {
return get_read_state()[chunk];
}
auto open_file::get_stop_requested() const -> bool {
return stop_requested_ || app_config::get_stop_requested();
}
auto open_file::is_complete() const -> bool { return get_read_state().all(); }
auto open_file::native_operation(
i_open_file::native_operation_callback callback) -> api_error {
if (stop_requested_) {
if (get_stop_requested()) {
return set_api_error(api_error::download_stopped);
}
@ -424,7 +428,7 @@ auto open_file::native_operation(
return set_api_error(api_error::invalid_operation);
}
if (stop_requested_) {
if (get_stop_requested()) {
return set_api_error(api_error::download_stopped);
}
@ -535,7 +539,7 @@ auto open_file::read(std::size_t read_size, std::uint64_t read_offset,
return set_api_error(api_error::invalid_operation);
}
if (stop_requested_) {
if (get_stop_requested()) {
return set_api_error(api_error::download_stopped);
}
@ -656,7 +660,7 @@ void open_file::update_reader(std::size_t chunk) {
recur_mutex_lock rw_lock(rw_mtx_);
read_chunk_ = chunk;
if (reader_thread_ || stop_requested_) {
if (reader_thread_ || get_stop_requested()) {
return;
}
@ -666,13 +670,13 @@ void open_file::update_reader(std::size_t chunk) {
auto read_chunk{read_chunk_};
lock.unlock();
while (not stop_requested_) {
while (not get_stop_requested()) {
lock.lock();
auto read_state = get_read_state();
if ((get_file_size() == 0U) || read_state.all()) {
lock.unlock();
wait_for_io(stop_requested_);
wait_for_io([this]() -> bool { return this->get_stop_requested(); });
continue;
}
@ -702,7 +706,7 @@ auto open_file::write(std::uint64_t write_offset, const data_buffer &data,
return api_error::success;
}
if (stop_requested_) {
if (get_stop_requested()) {
return set_api_error(api_error::download_stopped);
}

View File

@ -366,9 +366,9 @@ void open_file_base::set_api_path(const std::string &api_path) {
fsi_.api_parent = utils::path::get_parent_api_path(api_path);
}
void open_file_base::wait_for_io(stop_type &stop_requested) {
void open_file_base::wait_for_io(stop_type_callback stop_requested_cb) {
unique_mutex_lock io_lock(io_thread_mtx_);
if (not stop_requested && io_thread_queue_.empty()) {
if (not stop_requested_cb() && io_thread_queue_.empty()) {
io_thread_notify_.wait(io_lock);
}
io_thread_notify_.notify_all();

View File

@ -95,8 +95,8 @@ auto ring_buffer_base::close() -> bool {
return res;
}
auto ring_buffer_base::download_chunk(std::size_t chunk,
bool skip_active) -> api_error {
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();
@ -183,6 +183,10 @@ auto ring_buffer_base::get_read_state(std::size_t chunk) const -> bool {
return read_state_[chunk % read_state_.size()];
}
auto ring_buffer_base::get_stop_requested() const -> bool {
return stop_requested_ || app_config::get_stop_requested();
}
auto ring_buffer_base::read(std::size_t read_size, std::uint64_t read_offset,
data_buffer &data) -> api_error {
if (is_directory()) {
@ -207,7 +211,8 @@ auto ring_buffer_base::read(std::size_t read_size, std::uint64_t read_offset,
}
for (std::size_t chunk = begin_chunk;
not stop_requested_ && (res == api_error::success) && (read_size > 0U);
not get_stop_requested() && (res == api_error::success) &&
(read_size > 0U);
++chunk) {
reset_timeout();
@ -247,7 +252,7 @@ auto ring_buffer_base::read(std::size_t read_size, std::uint64_t read_offset,
read_offset = 0U;
}
return stop_requested_ ? api_error::download_stopped : res;
return get_stop_requested() ? api_error::download_stopped : res;
}
void ring_buffer_base::reader_thread() {
@ -256,12 +261,12 @@ void ring_buffer_base::reader_thread() {
chunk_notify_.notify_all();
chunk_lock.unlock();
while (not stop_requested_) {
while (not get_stop_requested()) {
chunk_lock.lock();
next_chunk = next_chunk + 1U > ring_end_ ? ring_begin_ : next_chunk + 1U;
const auto check_and_wait = [this, &chunk_lock, &next_chunk]() {
if (stop_requested_) {
if (get_stop_requested()) {
chunk_notify_.notify_all();
chunk_lock.unlock();
return;

View File

@ -37,12 +37,16 @@
namespace repertory {
void base_provider::add_all_items(stop_type &stop_requested) {
const auto get_stop_requested = [&stop_requested]() -> bool {
return stop_requested || app_config::get_stop_requested();
};
REPERTORY_USES_FUNCTION_NAME();
api_file_list list{};
std::string marker;
auto res{api_error::more_data};
while (not stop_requested && res == api_error::more_data) {
while (not get_stop_requested() && res == api_error::more_data) {
res = get_file_list(list, marker);
if (res != api_error::success && res != api_error::more_data) {
utils::error::raise_error(function_name, res, "failed to get file list");
@ -438,8 +442,12 @@ auto base_provider::is_file_writeable(const std::string &api_path) const
void base_provider::process_removed_directories(
std::deque<removed_item> removed_list, stop_type &stop_requested) {
const auto get_stop_requested = [&stop_requested]() -> bool {
return stop_requested || app_config::get_stop_requested();
};
for (const auto &item : removed_list) {
if (stop_requested) {
if (get_stop_requested()) {
return;
}
@ -457,10 +465,15 @@ void base_provider::process_removed_files(std::deque<removed_item> removed_list,
stop_type &stop_requested) {
REPERTORY_USES_FUNCTION_NAME();
auto orphaned_directory =
utils::path::combine(get_config().get_data_directory(), {"orphaned"});
const auto get_stop_requested = [&stop_requested]() -> bool {
return stop_requested || app_config::get_stop_requested();
};
auto orphaned_directory{
utils::path::combine(get_config().get_data_directory(), {"orphaned"}),
};
for (const auto &item : removed_list) {
if (stop_requested) {
if (get_stop_requested()) {
return;
}
@ -514,11 +527,15 @@ void base_provider::process_removed_files(std::deque<removed_item> removed_list,
}
void base_provider::process_removed_items(stop_type &stop_requested) {
const auto get_stop_requested = [&stop_requested]() -> bool {
return stop_requested || app_config::get_stop_requested();
};
db3_->enumerate_api_path_list(
[this, &stop_requested](auto &&list) {
[this, &get_stop_requested](auto &&list) {
[[maybe_unused]] auto res =
std::all_of(list.begin(), list.end(), [&](auto &&api_path) -> bool {
if (stop_requested) {
if (get_stop_requested()) {
return false;
}
@ -566,20 +583,24 @@ void base_provider::process_removed_items(stop_type &stop_requested) {
},
});
return not stop_requested;
return not get_stop_requested();
});
},
stop_requested);
get_stop_requested);
}
void base_provider::remove_deleted_items(stop_type &stop_requested) {
const auto get_stop_requested = [&stop_requested]() -> bool {
return stop_requested || app_config::get_stop_requested();
};
add_all_items(stop_requested);
if (stop_requested) {
if (get_stop_requested()) {
return;
}
remove_unmatched_source_files(stop_requested);
if (stop_requested) {
if (get_stop_requested()) {
return;
}
@ -673,12 +694,16 @@ void base_provider::remove_unmatched_source_files(stop_type &stop_requested) {
return;
}
const auto get_stop_requested = [&stop_requested]() -> bool {
return stop_requested || app_config::get_stop_requested();
};
const auto &cfg = get_config();
auto source_list =
utils::file::directory{cfg.get_cache_directory()}.get_files();
for (const auto &source_file : source_list) {
if (stop_requested) {
if (get_stop_requested()) {
return;
}
@ -740,26 +765,34 @@ auto base_provider::start(api_item_added_callback api_item_added,
auto online{false};
auto unmount_requested{false};
const auto get_stop_requested = [&unmount_requested]() -> bool {
return unmount_requested || app_config::get_stop_requested();
};
{
const auto &cfg = get_config();
repertory::event_consumer consumer(
"unmount_requested",
[&unmount_requested](const event &) { unmount_requested = true; });
for (std::uint16_t idx = 0U; not online && not unmount_requested &&
"unmount_requested", [&unmount_requested](const event & /* evt */) {
unmount_requested = true;
});
for (std::uint16_t idx = 0U; not online && not get_stop_requested() &&
(idx < cfg.get_online_check_retry_secs());
++idx) {
online = is_online();
if (not online) {
event_system::instance().raise<provider_offline>(
cfg.get_host_config().host_name_or_ip,
cfg.get_host_config().api_port);
std::this_thread::sleep_for(1s);
if (online) {
continue;
}
event_system::instance().raise<provider_offline>(
cfg.get_host_config().host_name_or_ip,
cfg.get_host_config().api_port);
std::this_thread::sleep_for(1s);
}
}
if (not online || unmount_requested) {
if (not online || get_stop_requested()) {
return false;
}

View File

@ -27,21 +27,22 @@
#include "types/repertory.hpp"
#include "types/startup_exception.hpp"
#include "utils/collection.hpp"
#include "utils/config.hpp"
#include "utils/encrypting_reader.hpp"
#include "utils/encryption.hpp"
#include "utils/error_utils.hpp"
#include "utils/file_utils.hpp"
#include "utils/path.hpp"
#include "utils/polling.hpp"
#include <utils/config.hpp>
namespace repertory {
encrypt_provider::encrypt_provider(app_config &config)
: config_(config), encrypt_config_(config.get_encrypt_config()) {}
auto encrypt_provider::create_api_file(
const std::string &api_path, bool directory,
const std::string &source_path) -> api_file {
auto encrypt_provider::create_api_file(const std::string &api_path,
bool directory,
const std::string &source_path)
-> api_file {
auto times{utils::file::get_times(source_path)};
if (not times.has_value()) {
throw std::runtime_error("failed to get file times");
@ -67,10 +68,10 @@ auto encrypt_provider::create_api_file(
void encrypt_provider::create_item_meta(api_meta_map &meta, bool directory,
const api_file &file) {
#if defined(_WIN32)
struct _stat64 buf {};
struct _stat64 buf{};
_stat64(file.source_path.c_str(), &buf);
#else // !defined(_WIN32)
struct stat buf {};
struct stat buf{};
stat(file.source_path.c_str(), &buf);
#endif // defined(_WIN32)
@ -150,8 +151,9 @@ auto encrypt_provider::do_fs_operation(
return callback(cfg, source_path);
}
auto encrypt_provider::get_api_path_from_source(
const std::string &source_path, std::string &api_path) const -> api_error {
auto encrypt_provider::get_api_path_from_source(const std::string &source_path,
std::string &api_path) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME();
try {
@ -191,8 +193,9 @@ auto encrypt_provider::get_directory_item_count(
return count;
}
auto encrypt_provider::get_directory_items(
const std::string &api_path, directory_item_list &list) const -> api_error {
auto encrypt_provider::get_directory_items(const std::string &api_path,
directory_item_list &list) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME();
return do_fs_operation(
@ -325,8 +328,9 @@ auto encrypt_provider::get_file(const std::string &api_path,
return api_error::error;
}
auto encrypt_provider::get_file_list(
api_file_list &list, std::string & /* marker */) const -> api_error {
auto encrypt_provider::get_file_list(api_file_list &list,
std::string & /* marker */) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME();
const auto &cfg{get_encrypt_config()};
@ -349,8 +353,9 @@ auto encrypt_provider::get_file_list(
return api_error::error;
}
auto encrypt_provider::get_file_size(
const std::string &api_path, std::uint64_t &file_size) const -> api_error {
auto encrypt_provider::get_file_size(const std::string &api_path,
std::uint64_t &file_size) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME();
try {
@ -371,9 +376,10 @@ auto encrypt_provider::get_file_size(
return api_error::error;
}
auto encrypt_provider::get_filesystem_item(
const std::string &api_path, bool directory,
filesystem_item &fsi) const -> api_error {
auto encrypt_provider::get_filesystem_item(const std::string &api_path,
bool directory,
filesystem_item &fsi) const
-> api_error {
std::string source_path;
if (directory) {
auto result{db_->get_directory_source_path(api_path, source_path)};
@ -424,9 +430,10 @@ auto encrypt_provider::get_filesystem_item_from_source_path(
return get_filesystem_item(api_path, false, fsi);
}
auto encrypt_provider::get_filesystem_item_and_file(
const std::string &api_path, api_file &file,
filesystem_item &fsi) const -> api_error {
auto encrypt_provider::get_filesystem_item_and_file(const std::string &api_path,
api_file &file,
filesystem_item &fsi) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME();
try {
@ -552,8 +559,8 @@ auto encrypt_provider::is_directory(const std::string &api_path,
return api_error::error;
}
auto encrypt_provider::is_file(const std::string &api_path,
bool &exists) const -> api_error {
auto encrypt_provider::is_file(const std::string &api_path, bool &exists) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME();
try {
@ -692,11 +699,11 @@ auto encrypt_provider::process_directory_entry(
}
if (file_res == api_error::item_not_found) {
stop_type stop_requested{false};
utils::encryption::encrypting_reader reader(
utils::path::strip_to_file_name(relative_path),
dir_entry.get_path(), stop_requested, cfg.encryption_token,
utils::path::get_parent_path(relative_path));
dir_entry.get_path(),
[]() -> bool { return app_config::get_stop_requested(); },
cfg.encryption_token, utils::path::get_parent_path(relative_path));
api_path = utils::path::create_api_path(
api_parent + "/" + reader.get_encrypted_file_name());
@ -757,7 +764,10 @@ auto encrypt_provider::read_file_bytes(const std::string &api_path,
auto info{std::make_shared<reader_info>()};
info->reader = std::make_unique<utils::encryption::encrypting_reader>(
relative_path, file_data.source_path, stop_requested,
relative_path, file_data.source_path,
[&stop_requested]() -> bool {
return stop_requested || app_config::get_stop_requested();
},
cfg.encryption_token, utils::path::get_parent_path(relative_path));
reader_lookup_[file_data.source_path] = info;
file_data.file_size = file_size;
@ -775,8 +785,11 @@ auto encrypt_provider::read_file_bytes(const std::string &api_path,
reader_lookup_.end()) {
auto info{std::make_shared<reader_info>()};
info->reader = std::make_unique<utils::encryption::encrypting_reader>(
api_path, file_data.source_path, stop_requested, cfg.encryption_token,
std::move(file_data.iv_list));
api_path, file_data.source_path,
[&stop_requested]() -> bool {
return stop_requested || app_config::get_stop_requested();
},
cfg.encryption_token, std::move(file_data.iv_list));
reader_lookup_[file_data.source_path] = info;
}
@ -802,11 +815,15 @@ auto encrypt_provider::read_file_bytes(const std::string &api_path,
void encrypt_provider::remove_deleted_files(stop_type &stop_requested) {
REPERTORY_USES_FUNCTION_NAME();
const auto get_stop_requested = [&stop_requested]() -> bool {
return stop_requested || app_config::get_stop_requested();
};
db_->enumerate_item_list(
[this, &stop_requested](auto &&list) {
[this, &get_stop_requested](auto &&list) {
std::vector<i_file_db::file_info> removed_list{};
for (const auto &item : list) {
if (stop_requested) {
if (get_stop_requested()) {
return;
}
@ -818,7 +835,7 @@ void encrypt_provider::remove_deleted_files(stop_type &stop_requested) {
}
for (const auto &item : removed_list) {
if (stop_requested) {
if (get_stop_requested()) {
return;
}
@ -841,7 +858,7 @@ void encrypt_provider::remove_deleted_files(stop_type &stop_requested) {
item.api_path, item.source_path);
}
},
stop_requested);
get_stop_requested);
}
auto encrypt_provider::start(api_item_added_callback /*api_item_added*/,

View File

@ -809,7 +809,8 @@ auto s3_provider::read_file_bytes(const std::string &api_path, std::size_t size,
data_buffer &read_buffer) -> api_error {
auto res{api_error::error};
for (std::uint32_t idx = 0U;
not stop_requested && res != api_error::success &&
not(stop_requested || app_config::get_stop_requested()) &&
res != api_error::success &&
idx < get_config().get_retry_read_count() + 1U;
++idx) {
curl::requests::http_get get{};
@ -1099,10 +1100,10 @@ auto s3_provider::upload_file_impl(const std::string &api_path,
}
if (is_encrypted && file_size > 0U) {
static stop_type no_stop{false};
put_file.reader = std::make_shared<utils::encryption::encrypting_reader>(
object_name, source_path, no_stop, cfg.encryption_token, -1);
object_name, source_path,
[]() -> bool { return app_config::get_stop_requested(); },
cfg.encryption_token, -1);
}
long response_code{};

View File

@ -568,7 +568,8 @@ auto sia_provider::read_file_bytes(const std::string &api_path,
auto res{api_error::comm_error};
for (std::uint32_t idx = 0U;
not stop_requested && res != api_error::success &&
not(stop_requested || app_config::get_stop_requested()) &&
res != api_error::success &&
idx < get_config().get_retry_read_count() + 1U;
++idx) {
long response_code{};

View File

@ -137,63 +137,71 @@ void server::start() {
REPERTORY_USES_FUNCTION_NAME();
mutex_lock lock(start_stop_mutex_);
if (not started_) {
event_system::instance().raise<service_started>("server");
server_ = std::make_unique<httplib::Server>();
server_->set_exception_handler([](const httplib::Request &req,
httplib::Response &res,
std::exception_ptr ep) {
json data = {{"path", req.path}};
try {
std::rethrow_exception(ep);
} catch (std::exception &e) {
data["error"] = e.what() ? e.what() : "unknown error";
utils::error::raise_error(function_name, e,
"failed request: " + req.path);
} catch (...) {
data["error"] = "unknown error";
utils::error::raise_error(function_name, "unknown error",
"failed request: " + req.path);
}
res.set_content(data.dump(), "application/json");
res.status = 500;
});
server_->set_pre_routing_handler(
[this](auto &&req, auto &&res) -> httplib::Server::HandlerResponse {
if (check_authorization(req)) {
return httplib::Server::HandlerResponse::Unhandled;
}
res.status = 401;
return httplib::Server::HandlerResponse::Handled;
});
initialize(*server_);
server_thread_ = std::make_unique<std::thread>(
[this]() { server_->listen("127.0.0.1", config_.get_api_port()); });
started_ = true;
if (server_thread_) {
return;
}
event_system::instance().raise<service_started>("server");
server_ = std::make_unique<httplib::Server>();
server_->set_exception_handler([](const httplib::Request &req,
httplib::Response &res,
std::exception_ptr ep) {
json data = {{"path", req.path}};
try {
std::rethrow_exception(ep);
} catch (std::exception &e) {
data["error"] = e.what() ? e.what() : "unknown error";
utils::error::raise_error(function_name, e,
"failed request: " + req.path);
} catch (...) {
data["error"] = "unknown error";
utils::error::raise_error(function_name, "unknown error",
"failed request: " + req.path);
}
res.set_content(data.dump(), "application/json");
res.status = 500;
});
server_->set_pre_routing_handler(
[this](auto &&req, auto &&res) -> httplib::Server::HandlerResponse {
if (check_authorization(req)) {
return httplib::Server::HandlerResponse::Unhandled;
}
res.status = 401;
return httplib::Server::HandlerResponse::Handled;
});
initialize(*server_);
server_thread_ = std::make_unique<std::thread>(
[this]() { server_->listen("127.0.0.1", config_.get_api_port()); });
}
void server::stop() {
if (started_) {
mutex_lock l(start_stop_mutex_);
if (started_) {
event_system::instance().raise<service_shutdown_begin>("server");
server_->stop();
server_thread_->join();
server_thread_.reset();
started_ = false;
event_system::instance().raise<service_shutdown_end>("server");
}
unique_mutex_lock lock(start_stop_mutex_);
if (not server_thread_) {
return;
}
event_system::instance().raise<service_shutdown_begin>("server");
server_->stop();
std::unique_ptr<std::thread> thread{nullptr};
std::swap(thread, server_thread_);
lock.unlock();
thread->join();
thread.reset();
lock.lock();
server_.reset();
lock.unlock();
event_system::instance().raise<service_shutdown_end>("server");
}
} // namespace repertory

View File

@ -81,6 +81,54 @@ auto download_type_to_string(const download_type &type) -> std::string {
}
}
auto event_level_from_string(std::string level, event_level default_level)
-> event_level {
level = utils::string::to_lower(level);
if (level == "critical" || level == "event_level::critical") {
return event_level::critical;
}
if (level == "debug" || level == "event_level::debug") {
return event_level::debug;
}
if (level == "warn" || level == "event_level::warn") {
return event_level::warn;
}
if (level == "info" || level == "event_level::info") {
return event_level::info;
}
if (level == "error" || level == "event_level::error") {
return event_level::error;
}
if (level == "trace" || level == "event_level::trace") {
return event_level::trace;
}
return default_level;
}
auto event_level_to_string(event_level level) -> std::string {
switch (level) {
case event_level::critical:
return "critical";
case event_level::debug:
return "debug";
case event_level::error:
return "error";
case event_level::info:
return "info";
case event_level::warn:
return "warn";
case event_level::trace:
return "trace";
default:
return "info";
}
}
static const std::unordered_map<api_error, std::string> LOOKUP = {
{api_error::success, "success"},
{api_error::access_denied, "access_denied"},

View File

@ -31,7 +31,7 @@ polling polling::instance_;
void polling::frequency_thread(
std::function<std::uint32_t()> get_frequency_seconds, frequency freq) {
while (not stop_requested_) {
while (not get_stop_requested()) {
unique_mutex_lock lock(mutex_);
auto futures = std::accumulate(
items_.begin(), items_.end(), std::deque<tasks::task_ptr>{},
@ -65,7 +65,7 @@ void polling::frequency_thread(
futures.pop_front();
}
if (stop_requested_) {
if (get_stop_requested()) {
return;
}
@ -74,6 +74,10 @@ void polling::frequency_thread(
}
}
auto polling::get_stop_requested() const -> bool {
return stop_requested_ || app_config::get_stop_requested();
}
void polling::remove_callback(const std::string &name) {
mutex_lock lock(mutex_);
items_.erase(name);
@ -138,15 +142,20 @@ void polling::stop() {
}
event_system::instance().raise<service_shutdown_begin>("polling");
stop_requested_ = true;
tasks::instance().stop();
unique_mutex_lock thread_lock(mutex_);
std::array<std::unique_ptr<std::thread>,
static_cast<std::size_t>(frequency::size)>
threads;
std::swap(threads, frequency_threads_);
notify_.notify_all();
thread_lock.unlock();
for (auto &&thread : frequency_threads_) {
for (auto &thread : threads) {
thread->join();
thread.reset();
}

View File

@ -21,11 +21,16 @@
*/
#include "utils/single_thread_service_base.hpp"
#include "app_config.hpp"
#include "events/event_system.hpp"
#include "events/events.hpp"
#include "types/repertory.hpp"
namespace repertory {
auto single_thread_service_base::get_stop_requested() const -> bool {
return stop_requested_ || app_config::get_stop_requested();
}
void single_thread_service_base::notify_all() const {
mutex_lock lock(get_mutex());
notify_.notify_all();
@ -33,33 +38,41 @@ void single_thread_service_base::notify_all() const {
void single_thread_service_base::start() {
mutex_lock lock(mtx_);
if (not thread_) {
stop_requested_ = false;
on_start();
thread_ = std::make_unique<std::thread>([this]() {
event_system::instance().raise<service_started>(service_name_);
while (not stop_requested_) {
service_function();
}
});
if (thread_) {
return;
}
stop_requested_ = false;
on_start();
thread_ = std::make_unique<std::thread>([this]() {
event_system::instance().raise<service_started>(service_name_);
while (not get_stop_requested()) {
service_function();
}
});
}
void single_thread_service_base::stop() {
if (thread_) {
event_system::instance().raise<service_shutdown_begin>(service_name_);
unique_mutex_lock lock(mtx_);
if (thread_) {
stop_requested_ = true;
notify_.notify_all();
lock.unlock();
thread_->join();
thread_.reset();
on_stop();
}
event_system::instance().raise<service_shutdown_end>(service_name_);
unique_mutex_lock lock(mtx_);
if (not thread_) {
return;
}
event_system::instance().raise<service_shutdown_begin>(service_name_);
stop_requested_ = true;
std::unique_ptr<std::thread> thread{nullptr};
std::swap(thread, thread_);
notify_.notify_all();
lock.unlock();
thread->join();
thread.reset();
on_stop();
event_system::instance().raise<service_shutdown_end>(service_name_);
}
} // namespace repertory

View File

@ -27,6 +27,10 @@
namespace repertory {
tasks tasks::instance_;
auto tasks::get_stop_requested() const -> bool {
return stop_requested_ || app_config::get_stop_requested();
}
void tasks::task_wait::set_result(bool result) {
unique_mutex_lock lock(mtx);
if (complete) {
@ -50,7 +54,7 @@ auto tasks::task_wait::wait() const -> bool {
auto tasks::schedule(task item) -> task_ptr {
++count_;
while (not stop_requested_ && (count_ >= task_threads_.size())) {
while (not get_stop_requested() && (count_ >= task_threads_.size())) {
std::this_thread::sleep_for(
std::chrono::milliseconds(config_->get_task_wait_ms()));
}
@ -58,7 +62,7 @@ auto tasks::schedule(task item) -> task_ptr {
scheduled_task runnable{item};
unique_mutex_lock lock(mutex_);
if (stop_requested_) {
if (get_stop_requested()) {
runnable.wait->set_result(false);
notify_.notify_all();
return runnable.wait;
@ -96,15 +100,17 @@ void tasks::stop() {
stop_requested_ = true;
unique_mutex_lock lock(mutex_);
std::vector<std::unique_ptr<std::jthread>> threads;
std::swap(threads, task_threads_);
std::deque<scheduled_task> task_list;
std::swap(task_list, tasks_);
notify_.notify_all();
lock.unlock();
task_threads_.clear();
lock.lock();
tasks_.clear();
notify_.notify_all();
lock.unlock();
threads.clear();
task_list.clear();
}
void tasks::task_thread() {
@ -119,14 +125,14 @@ void tasks::task_thread() {
release();
while (not stop_requested_) {
while (not get_stop_requested()) {
lock.lock();
while (not stop_requested_ && tasks_.empty()) {
while (not get_stop_requested() && tasks_.empty()) {
notify_.wait(lock);
}
if (stop_requested_) {
if (get_stop_requested()) {
release();
return;
}

View File

@ -27,28 +27,33 @@ namespace repertory {
timeout::timeout(std::function<void()> timeout_callback,
const std::chrono::system_clock::duration &duration)
: timeout_killed_(duration == 0s) {
if (not timeout_killed_) {
timeout_thread_ =
std::make_unique<std::thread>([this, duration, timeout_callback]() {
unique_mutex_lock lock(timeout_mutex_);
if (not timeout_killed_) {
timeout_notify_.wait_for(lock, duration);
if (not timeout_killed_) {
timeout_callback();
}
}
});
if (timeout_killed_) {
return;
}
timeout_thread_ =
std::make_unique<std::thread>([this, duration, timeout_callback]() {
unique_mutex_lock lock(timeout_mutex_);
if (not timeout_killed_) {
timeout_notify_.wait_for(lock, duration);
if (not timeout_killed_) {
timeout_callback();
}
}
});
}
void timeout::disable() {
if (not timeout_killed_) {
timeout_killed_ = true;
unique_mutex_lock lock(timeout_mutex_);
timeout_notify_.notify_all();
lock.unlock();
timeout_thread_->join();
timeout_thread_.reset();
if (timeout_killed_) {
return;
}
timeout_killed_ = true;
unique_mutex_lock lock(timeout_mutex_);
timeout_notify_.notify_all();
lock.unlock();
timeout_thread_->join();
timeout_thread_.reset();
}
} // namespace repertory

View File

@ -19,6 +19,8 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "rocksdb/table.h"
#include "utils/utils.hpp"
#include "app_config.hpp"
@ -38,12 +40,9 @@ void calculate_allocation_size(bool directory, std::uint64_t file_size,
return;
}
if (file_size > allocation_size) {
allocation_size = file_size;
}
allocation_size =
utils::divide_with_ceiling(allocation_size, WINFSP_ALLOCATION_UNIT) *
utils::divide_with_ceiling(std::max(file_size, allocation_size),
WINFSP_ALLOCATION_UNIT) *
WINFSP_ALLOCATION_UNIT;
allocation_meta_size = std::to_string(allocation_size);
}
@ -51,8 +50,8 @@ void calculate_allocation_size(bool directory, std::uint64_t file_size,
auto create_rocksdb(
const app_config &cfg, const std::string &name,
const std::vector<rocksdb::ColumnFamilyDescriptor> &families,
std::vector<rocksdb::ColumnFamilyHandle *> &handles,
bool clear) -> std::unique_ptr<rocksdb::TransactionDB> {
std::vector<rocksdb::ColumnFamilyHandle *> &handles, bool clear)
-> std::unique_ptr<rocksdb::TransactionDB> {
REPERTORY_USES_FUNCTION_NAME();
auto db_dir = utils::path::combine(cfg.get_data_directory(), {"db"});

View File

@ -22,6 +22,10 @@
#include "fixtures/file_db_fixture.hpp"
namespace {
const auto get_stop_requested = []() -> bool { return false; };
} // namespace
namespace repertory {
TYPED_TEST_CASE(file_db_test, file_db_types);
@ -30,8 +34,7 @@ TYPED_TEST(file_db_test, can_add_and_remove_directory) {
EXPECT_EQ(api_error::success, this->file_db->add_directory("/", "c:\\test"));
stop_type stop_requested{false};
auto list = this->file_db->get_item_list(stop_requested);
auto list = this->file_db->get_item_list(get_stop_requested);
EXPECT_EQ(1U, list.size());
EXPECT_STREQ("/", list.at(0U).api_path.c_str());
EXPECT_TRUE(list.at(0U).directory);
@ -39,7 +42,7 @@ TYPED_TEST(file_db_test, can_add_and_remove_directory) {
EXPECT_EQ(api_error::success, this->file_db->remove_item("/"));
list = this->file_db->get_item_list(stop_requested);
list = this->file_db->get_item_list(get_stop_requested);
EXPECT_EQ(0U, list.size());
}
@ -53,8 +56,7 @@ TYPED_TEST(file_db_test, can_add_and_remove_file) {
"c:\\test\\file.txt",
}));
stop_type stop_requested{false};
auto list = this->file_db->get_item_list(stop_requested);
auto list = this->file_db->get_item_list(get_stop_requested);
EXPECT_EQ(1U, list.size());
EXPECT_STREQ("/file", list.at(0U).api_path.c_str());
EXPECT_FALSE(list.at(0U).directory);
@ -62,7 +64,7 @@ TYPED_TEST(file_db_test, can_add_and_remove_file) {
EXPECT_EQ(api_error::success, this->file_db->remove_item("/file"));
list = this->file_db->get_item_list(stop_requested);
list = this->file_db->get_item_list(get_stop_requested);
EXPECT_EQ(0U, list.size());
}

View File

@ -21,7 +21,7 @@
*/
#include "fixtures/file_mgr_db_fixture.hpp"
#include <utils/time.hpp>
#include "utils/time.hpp"
namespace repertory {
TYPED_TEST_CASE(file_mgr_db_test, file_mgr_db_types);

View File

@ -103,7 +103,7 @@ TYPED_TEST(fuse_test, access_directory_permutations_test) {
std::string dir_name{"access_test"};
auto dir_path = this->create_directory_and_test(dir_name);
for (auto &&permutation : access_permutations) {
for (const auto &permutation : access_permutations) {
perform_access_test(permutation, dir_path);
}
@ -114,7 +114,7 @@ TYPED_TEST(fuse_test, access_file_permutations_test) {
std::string file_name{"access_test"};
auto file_path = this->create_file_and_test(file_name);
for (auto &&permutation : access_permutations) {
for (const auto &permutation : access_permutations) {
perform_access_test(permutation, file_path);
}

View File

@ -41,7 +41,7 @@ TYPED_TEST(fuse_test, create_can_create_directory_with_specific_perms) {
std::string dir_name{"create_test"};
auto dir_path = this->create_directory_and_test(dir_name, S_IRUSR);
struct stat64 unix_st {};
struct stat64 unix_st{};
EXPECT_EQ(0, stat64(dir_path.c_str(), &unix_st));
EXPECT_EQ(S_IRUSR, unix_st.st_mode & ACCESSPERMS);
@ -52,7 +52,7 @@ TYPED_TEST(fuse_test, create_can_create_file_with_specific_perms) {
std::string file_name{"create_test"};
auto file_path = this->create_file_and_test(file_name, S_IRUSR);
struct stat64 unix_st {};
struct stat64 unix_st{};
EXPECT_EQ(0, stat64(file_path.c_str(), &unix_st));
EXPECT_EQ(S_IRUSR, unix_st.st_mode & ACCESSPERMS);
@ -376,7 +376,7 @@ TYPED_TEST(fuse_test, create_fails_with_excl_if_path_is_directory) {
std::string dir_name{"create_test"};
auto dir_path = this->create_directory_and_test(dir_name);
for (auto &&flags : ops) {
for (const auto &flags : ops) {
auto handle = open(dir_path.c_str(), flags, ACCESSPERMS);
EXPECT_EQ(-1, handle);
@ -396,7 +396,7 @@ TYPED_TEST(fuse_test, create_fails_with_excl_if_file_exists) {
std::string file_name{"create_test"};
auto file_path = this->create_file_and_test(file_name);
for (auto &&flags : ops) {
for (const auto &flags : ops) {
auto handle = open(file_path.c_str(), flags, ACCESSPERMS);
EXPECT_EQ(-1, handle);
@ -420,7 +420,7 @@ TYPED_TEST(fuse_test, create_fails_if_path_is_directory) {
std::string dir_name{"create_test"};
auto dir_path = this->create_directory_and_test(dir_name);
for (auto &&flags : ops) {
for (const auto &flags : ops) {
auto handle = open(dir_path.c_str(), flags, ACCESSPERMS);
EXPECT_EQ(-1, handle);
@ -447,7 +447,7 @@ TYPED_TEST(fuse_test, create_fails_if_parent_path_does_not_exist) {
std::string file_name{"no_dir/create_test"};
auto file_path = this->create_file_path(file_name);
for (auto &&flags : ops) {
for (const auto &flags : ops) {
auto handle = open(file_path.c_str(), flags, ACCESSPERMS);
EXPECT_EQ(-1, handle);
@ -463,7 +463,7 @@ TYPED_TEST(fuse_test, create_fails_if_invalid) {
std::string file_name{"create_test"};
auto file_path = this->create_file_path(file_name);
for (auto &&flags : ops) {
for (const auto &flags : ops) {
auto handle = open(file_path.c_str(), flags, ACCESSPERMS);
EXPECT_EQ(-1, handle);
@ -481,7 +481,7 @@ TYPED_TEST(fuse_test, create_open_fails_if_path_is_directory) {
std::string dir_name{"create_test"};
auto dir_path = this->create_directory_and_test(dir_name);
for (auto &&flags : ops) {
for (const auto &flags : ops) {
auto handle = open(dir_path.c_str(), flags);
EXPECT_EQ(-1, handle);
if (handle != -1) {
@ -510,7 +510,7 @@ TYPED_TEST(fuse_test, create_open_fails_if_path_does_not_exist) {
std::string file_name{"create_test"};
auto file_path = this->create_file_path(file_name);
for (auto &&flags : ops) {
for (const auto &flags : ops) {
auto handle = open(file_path.c_str(), flags);
EXPECT_EQ(-1, handle);
EXPECT_EQ(ENOENT, errno);

View File

@ -97,7 +97,7 @@ TYPED_TEST(winfsp_test, cr8_file_can_delete_file_after_close) {
TYPED_TEST(winfsp_test,
cr8_file_cannot_create_files_with_invalid_characters_in_path) {
for (auto &&invalid_char : std::array<std::string, 7U>{
for (const auto &invalid_char : std::array<std::string, 7U>{
{"*", ":", "<", ">", "?", "|", "\""},
}) {
auto handle = ::CreateFileA(

View File

@ -416,6 +416,7 @@ using data_buffer = std::vector<unsigned char>;
using mutex_lock = std::lock_guard<std::mutex>;
using recur_mutex_lock = std::lock_guard<std::recursive_mutex>;
using stop_type = std::atomic_bool;
using stop_type_callback = std::function<std::atomic_bool()>;
using unique_mutex_lock = std::unique_lock<std::mutex>;
using unique_recur_mutex_lock = std::unique_lock<std::recursive_mutex>;

View File

@ -32,17 +32,19 @@ namespace repertory::utils::encryption {
class encrypting_reader final {
public:
encrypting_reader(std::string_view file_name, std::string_view source_path,
stop_type &stop_requested, std::string_view token,
stop_type_callback stop_requested_cb,
std::string_view token,
std::optional<std::string> relative_parent_path,
std::size_t error_return = 0U);
encrypting_reader(std::string_view encrypted_file_path,
std::string_view source_path, stop_type &stop_requested,
std::string_view source_path,
stop_type_callback stop_requested_cb,
std::string_view token, std::size_t error_return = 0U);
encrypting_reader(
std::string_view encrypted_file_path, std::string_view source_path,
stop_type &stop_requested, std::string_view token,
stop_type_callback stop_requested_cb, std::string_view token,
std::vector<std::array<unsigned char,
crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>
iv_list,
@ -62,7 +64,7 @@ public:
private:
utils::encryption::hash_256_t key_;
stop_type &stop_requested_;
stop_type_callback stop_requested_cb_;
size_t error_return_;
std::unique_ptr<utils::file::i_file> source_file_;
@ -126,7 +128,7 @@ public:
}
[[nodiscard]] auto get_stop_requested() const -> bool {
return stop_requested_;
return stop_requested_cb_();
}
[[nodiscard]] auto get_total_size() const -> std::uint64_t {

View File

@ -40,8 +40,8 @@ class encrypting_streambuf final : public encrypting_reader::streambuf {
public:
encrypting_streambuf(const encrypting_streambuf &) = default;
encrypting_streambuf(encrypting_streambuf &&) = delete;
auto
operator=(const encrypting_streambuf &) -> encrypting_streambuf & = delete;
auto operator=(const encrypting_streambuf &)
-> encrypting_streambuf & = delete;
auto operator=(encrypting_streambuf &&) -> encrypting_streambuf & = delete;
explicit encrypting_streambuf(const encrypting_reader &reader)
@ -93,9 +93,10 @@ protected:
return encrypting_reader::streambuf::seekoff(off, dir, which);
}
auto seekpos(pos_type pos, std::ios_base::openmode which =
std::ios_base::out |
std::ios_base::in) -> pos_type override {
auto seekpos(pos_type pos,
std::ios_base::openmode which = std::ios_base::out |
std::ios_base::in)
-> pos_type override {
return seekoff(pos, std::ios_base::beg, which);
}
@ -177,16 +178,16 @@ const std::size_t encrypting_reader::encrypted_chunk_size_ =
encrypting_reader::encrypting_reader(
std::string_view file_name, std::string_view source_path,
stop_type &stop_requested, std::string_view token,
stop_type_callback stop_requested_cb, std::string_view token,
std::optional<std::string> relative_parent_path, std::size_t error_return)
: key_(utils::encryption::generate_key<utils::encryption::hash_256_t>(
token)),
stop_requested_(stop_requested),
stop_requested_cb_(std::move(stop_requested_cb)),
error_return_(error_return),
source_file_(utils::file::file::open_or_create_file(source_path, true)) {
REPERTORY_USES_FUNCTION_NAME();
if (not *source_file_) {
if (not*source_file_) {
throw utils::error::create_exception(function_name, {
"file open failed",
source_path,
@ -237,17 +238,17 @@ encrypting_reader::encrypting_reader(
encrypting_reader::encrypting_reader(std::string_view encrypted_file_path,
std::string_view source_path,
stop_type &stop_requested,
stop_type_callback stop_requested_cb,
std::string_view token,
std::size_t error_return)
: key_(utils::encryption::generate_key<utils::encryption::hash_256_t>(
token)),
stop_requested_(stop_requested),
stop_requested_cb_(std::move(stop_requested_cb)),
error_return_(error_return),
source_file_(utils::file::file::open_or_create_file(source_path, true)) {
REPERTORY_USES_FUNCTION_NAME();
if (not *source_file_) {
if (not*source_file_) {
throw utils::error::create_exception(function_name, {
"file open failed",
source_path,
@ -283,19 +284,19 @@ encrypting_reader::encrypting_reader(std::string_view encrypted_file_path,
encrypting_reader::encrypting_reader(
std::string_view encrypted_file_path, std::string_view source_path,
stop_type &stop_requested, std::string_view token,
stop_type_callback stop_requested_cb, std::string_view token,
std::vector<
std::array<unsigned char, crypto_aead_xchacha20poly1305_IETF_NPUBBYTES>>
iv_list,
std::size_t error_return)
: key_(utils::encryption::generate_key<utils::encryption::hash_256_t>(
token)),
stop_requested_(stop_requested),
stop_requested_cb_(std::move(stop_requested_cb)),
error_return_(error_return),
source_file_(utils::file::file::open_or_create_file(source_path, true)) {
REPERTORY_USES_FUNCTION_NAME();
if (not *source_file_) {
if (not*source_file_) {
throw utils::error::create_exception(function_name, {
"file open failed",
source_path,
@ -329,7 +330,7 @@ encrypting_reader::encrypting_reader(
encrypting_reader::encrypting_reader(const encrypting_reader &reader)
: key_(reader.key_),
stop_requested_(reader.stop_requested_),
stop_requested_cb_(reader.stop_requested_cb_),
error_return_(reader.error_return_),
source_file_(
utils::file::file::open_file(reader.source_file_->get_path(), true)),
@ -343,7 +344,7 @@ encrypting_reader::encrypting_reader(const encrypting_reader &reader)
total_size_(reader.total_size_) {
REPERTORY_USES_FUNCTION_NAME();
if (not *source_file_) {
if (not*source_file_) {
throw utils::error::create_exception(
function_name, {
"file open failed",
@ -403,7 +404,7 @@ auto encrypting_reader::reader_function(char *buffer, size_t size,
try {
ret = true;
auto remain = read_size;
while (not stop_requested_ && ret && (remain != 0U)) {
while (not get_stop_requested() && ret && (remain != 0U)) {
if (chunk_buffers_.find(chunk) == chunk_buffers_.end()) {
auto &chunk_buffer = chunk_buffers_[chunk];
data_buffer file_data(chunk == last_data_chunk_
@ -441,9 +442,9 @@ auto encrypting_reader::reader_function(char *buffer, size_t size,
}
}
return stop_requested_ ? static_cast<std::size_t>(CURL_READFUNC_ABORT)
: ret ? total_read
: error_return_;
return get_stop_requested() ? static_cast<std::size_t>(CURL_READFUNC_ABORT)
: ret ? total_read
: error_return_;
}
} // namespace repertory::utils::encryption

View File

@ -23,6 +23,10 @@
#if defined(PROJECT_ENABLE_LIBSODIUM) && defined(PROJECT_ENABLE_BOOST)
namespace {
const auto get_stop_requested = []() -> bool { return false; };
} // namespace
namespace repertory {
TEST(utils_encrypting_reader, read_file_data) {
const auto token = std::string("moose");
@ -30,9 +34,8 @@ TEST(utils_encrypting_reader, read_file_data) {
8U * utils::encryption::encrypting_reader::get_data_chunk_size());
EXPECT_TRUE(source_file);
if (source_file) {
stop_type stop_requested{false};
utils::encryption::encrypting_reader reader(
"test.dat", source_file.get_path(), stop_requested, token);
"test.dat", source_file.get_path(), get_stop_requested, token);
for (std::uint8_t i = 0U; i < 8U; i++) {
data_buffer buffer(
@ -70,9 +73,8 @@ TEST(utils_encrypting_reader, read_file_data_in_multiple_chunks) {
8U * utils::encryption::encrypting_reader::get_data_chunk_size());
EXPECT_TRUE(source_file);
if (source_file) {
stop_type stop_requested{false};
utils::encryption::encrypting_reader reader(
"test.dat", source_file.get_path(), stop_requested, token);
"test.dat", source_file.get_path(), get_stop_requested, token);
for (std::uint8_t i = 0U; i < 8U; i += 2U) {
data_buffer buffer(
@ -118,9 +120,8 @@ TEST(utils_encrypting_reader, read_file_data_as_stream) {
8U * utils::encryption::encrypting_reader::get_data_chunk_size());
EXPECT_TRUE(source_file);
if (source_file) {
stop_type stop_requested{false};
utils::encryption::encrypting_reader reader(
"test.dat", source_file.get_path(), stop_requested, token);
"test.dat", source_file.get_path(), get_stop_requested, token);
auto io_stream = reader.create_iostream();
EXPECT_FALSE(io_stream->seekg(0, std::ios_base::end).fail());
EXPECT_TRUE(io_stream->good());
@ -171,9 +172,8 @@ TEST(utils_encrypting_reader, read_file_data_in_multiple_chunks_as_stream) {
8u * utils::encryption::encrypting_reader::get_data_chunk_size());
EXPECT_TRUE(source_file);
if (source_file) {
stop_type stop_requested{false};
utils::encryption::encrypting_reader reader(
"test.dat", source_file.get_path(), stop_requested, token);
"test.dat", source_file.get_path(), get_stop_requested, token);
auto io_stream = reader.create_iostream();
EXPECT_FALSE(io_stream->seekg(0, std::ios_base::end).fail());
EXPECT_TRUE(io_stream->good());

View File

@ -23,6 +23,10 @@
#if defined(PROJECT_ENABLE_LIBSODIUM)
namespace {
const auto get_stop_requested = []() -> bool { return false; };
} // namespace
namespace repertory {
static constexpr const std::string_view token{"moose"};
static constexpr const std::wstring_view token_w{L"moose"};
@ -250,9 +254,8 @@ TEST(utils_encryption, decrypt_file_name) {
8U * utils::encryption::encrypting_reader::get_data_chunk_size());
EXPECT_TRUE(source_file);
if (source_file) {
stop_type stop_requested{false};
utils::encryption::encrypting_reader reader(
"test.dat", source_file.get_path(), stop_requested, token,
"test.dat", source_file.get_path(), get_stop_requested, token,
std::nullopt);
auto file_name = reader.get_encrypted_file_name();
@ -267,9 +270,9 @@ TEST(utils_encryption, decrypt_file_path) {
8U * utils::encryption::encrypting_reader::get_data_chunk_size());
EXPECT_TRUE(source_file);
if (source_file) {
stop_type stop_requested{false};
utils::encryption::encrypting_reader reader(
"test.dat", source_file.get_path(), stop_requested, token, "moose/cow");
"test.dat", source_file.get_path(), get_stop_requested, token,
"moose/cow");
auto file_path = reader.get_encrypted_file_path();