28 Commits

Author SHA1 Message Date
0bbf6b5942 refactor
All checks were successful
BlockStorage/repertory/pipeline/head This commit looks good
2025-01-02 14:24:58 -06:00
74ef36956d re-enable cleanup 2025-01-02 14:22:40 -06:00
bbe065819c refactor 2025-01-02 14:22:17 -06:00
3493054f1a handle remove error 2025-01-02 14:20:20 -06:00
743281497c refactor 2025-01-02 14:14:21 -06:00
eaa6a6f92e refactor cleanup 2025-01-02 14:01:16 -06:00
a25dd8178e refactor cleanup 2025-01-02 13:43:22 -06:00
71463bfee4 refactor 2025-01-02 12:07:01 -06:00
270df62dbe refactor 2025-01-02 12:01:45 -06:00
5bd7ded7d9 refactor 2025-01-02 11:59:01 -06:00
b5048a422f refactor 2025-01-02 11:56:12 -06:00
c27528fe73 begin working on better handling of removed files 2025-01-02 10:27:52 -06:00
c3978562d5 cleanup 2025-01-02 08:59:19 -06:00
637892cff1 refactor 2025-01-02 08:58:02 -06:00
998a3d9d83 updated test 2025-01-02 08:50:44 -06:00
8ed8822625 refactor 2025-01-02 08:38:43 -06:00
196abaebcc refactor 2025-01-02 08:36:55 -06:00
653e8000ff refactor 2025-01-02 08:34:51 -06:00
ea362211aa fix 2025-01-02 08:32:42 -06:00
a4a9d069d3 fix 2025-01-02 08:27:45 -06:00
9cb7f9accf updated CHANGELOG.md 2025-01-02 08:19:42 -06:00
4e5454efb5 always use direct for read-only providers 2025-01-02 08:19:10 -06:00
a8c3f31298 refactor 2025-01-02 07:59:07 -06:00
f3093c27cd refactor 2025-01-02 07:57:07 -06:00
4526a9d860 refactor 2025-01-02 07:50:58 -06:00
a1ada5aa8c refactor 2025-01-02 07:48:56 -06:00
1ae8b8b793 refactor 2025-01-02 07:45:08 -06:00
f44cc99a82 refactor 2025-01-02 07:08:12 -06:00
29 changed files with 813 additions and 597 deletions

View File

@@ -15,6 +15,7 @@
### Changes from v2.0.2-rc ### Changes from v2.0.2-rc
* Always use direct for read-only providers
* Updated build system to Alpine 3.21.0 * Updated build system to Alpine 3.21.0
* Updated build system to MinGW-w64 12.0.0 * Updated build system to MinGW-w64 12.0.0
* Updated copyright to 2018-2025 * Updated copyright to 2018-2025

View File

@@ -31,7 +31,7 @@ class i_file_db {
public: public:
struct file_info final { struct file_info final {
std::string api_path; std::string api_path;
bool directory; bool directory{};
std::string source_path; std::string source_path;
}; };
@@ -56,6 +56,10 @@ public:
[[nodiscard]] virtual auto count() const -> std::uint64_t = 0; [[nodiscard]] virtual auto count() const -> std::uint64_t = 0;
virtual void enumerate_item_list(
std::function<void(const std::vector<i_file_db::file_info> &)> callback,
stop_type &stop_requested) const = 0;
[[nodiscard]] virtual auto get_api_path(const std::string &source_path, [[nodiscard]] virtual auto get_api_path(const std::string &source_path,
std::string &api_path) const std::string &api_path) const
-> api_error = 0; -> api_error = 0;
@@ -80,7 +84,7 @@ public:
get_file_source_path(const std::string &api_path, get_file_source_path(const std::string &api_path,
std::string &source_path) const -> api_error = 0; std::string &source_path) const -> api_error = 0;
[[nodiscard]] virtual auto get_item_list() const [[nodiscard]] virtual auto get_item_list(stop_type &stop_requested) const
-> std::vector<file_info> = 0; -> std::vector<file_info> = 0;
[[nodiscard]] virtual auto get_source_path(const std::string &api_path, [[nodiscard]] virtual auto get_source_path(const std::string &api_path,

View File

@@ -41,45 +41,42 @@ public:
std::string source_path; std::string source_path;
}; };
struct upload_entry final { using upload_entry = upload_active_entry;
std::string api_path;
std::string source_path;
};
public: public:
[[nodiscard]] virtual auto add_resume(const resume_entry &entry) -> bool = 0; [[nodiscard]] virtual auto add_resume(const resume_entry &entry) -> bool = 0;
[[nodiscard]] virtual auto add_upload(const upload_entry &entry) -> bool = 0; [[nodiscard]] virtual auto add_upload(const upload_entry &entry) -> bool = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto add_upload_active(const upload_active_entry &entry)
add_upload_active(const upload_active_entry &entry) -> bool = 0; -> bool = 0;
virtual void clear() = 0; virtual void clear() = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto get_next_upload() const
get_next_upload() const -> std::optional<upload_entry> = 0; -> std::optional<upload_entry> = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto get_resume_list() const
get_resume_list() const -> std::vector<resume_entry> = 0; -> std::vector<resume_entry> = 0;
[[nodiscard]] virtual auto get_upload(const std::string &api_path) const [[nodiscard]] virtual auto get_upload(const std::string &api_path) const
-> std::optional<upload_entry> = 0; -> std::optional<upload_entry> = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto get_upload_active_list() const
get_upload_active_list() const -> std::vector<upload_active_entry> = 0; -> std::vector<upload_active_entry> = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto remove_resume(const std::string &api_path)
remove_resume(const std::string &api_path) -> bool = 0; -> bool = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto remove_upload(const std::string &api_path)
remove_upload(const std::string &api_path) -> bool = 0; -> bool = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto remove_upload_active(const std::string &api_path)
remove_upload_active(const std::string &api_path) -> bool = 0; -> bool = 0;
[[nodiscard]] virtual auto [[nodiscard]] virtual auto rename_resume(const std::string &from_api_path,
rename_resume(const std::string &from_api_path, const std::string &to_api_path)
const std::string &to_api_path) -> bool = 0; -> bool = 0;
}; };
} // namespace repertory } // namespace repertory

View File

@@ -31,6 +31,10 @@ class i_meta_db {
public: public:
virtual void clear() = 0; virtual void clear() = 0;
virtual void enumerate_api_path_list(
std::function<void(const std::vector<std::string> &)> callback,
stop_type &stop_requested) const = 0;
[[nodiscard]] virtual auto get_api_path(const std::string &source_path, [[nodiscard]] virtual auto get_api_path(const std::string &source_path,
std::string &api_path) const std::string &api_path) const
-> api_error = 0; -> api_error = 0;

View File

@@ -67,50 +67,54 @@ private:
rocksdb::Transaction *txn) -> rocksdb::Status; rocksdb::Transaction *txn) -> rocksdb::Status;
public: public:
[[nodiscard]] auto [[nodiscard]] auto add_directory(const std::string &api_path,
add_directory(const std::string &api_path, const std::string &source_path)
const std::string &source_path) -> api_error override; -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto add_or_update_file(const i_file_db::file_data &data)
add_or_update_file(const i_file_db::file_data &data) -> api_error override; -> api_error override;
void clear() override; void clear() override;
[[nodiscard]] auto count() const -> std::uint64_t override; [[nodiscard]] auto count() const -> std::uint64_t override;
[[nodiscard]] auto void enumerate_item_list(
get_api_path(const std::string &source_path, std::function<void(const std::vector<i_file_db::file_info> &)> callback,
std::string &api_path) const -> api_error override; stop_type &stop_requested) const override;
[[nodiscard]] auto [[nodiscard]] auto get_api_path(const std::string &source_path,
get_directory_api_path(const std::string &source_path, std::string &api_path) const
std::string &api_path) const -> api_error override; -> api_error override;
[[nodiscard]] auto get_directory_api_path(const std::string &source_path,
std::string &api_path) const
-> api_error override;
[[nodiscard]] auto get_directory_source_path(const std::string &api_path, [[nodiscard]] auto get_directory_source_path(const std::string &api_path,
std::string &source_path) const std::string &source_path) const
-> api_error override; -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto get_file_api_path(const std::string &source_path,
get_file_api_path(const std::string &source_path, std::string &api_path) const
std::string &api_path) const -> api_error override; -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto get_file_data(const std::string &api_path,
get_file_data(const std::string &api_path, i_file_db::file_data &data) const
i_file_db::file_data &data) const -> api_error override; -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto get_file_source_path(const std::string &api_path,
get_file_source_path(const std::string &api_path, std::string &source_path) const
std::string &source_path) const -> api_error override; -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto get_item_list(stop_type &stop_requested) const
get_item_list() const -> std::vector<i_file_db::file_info> override; -> std::vector<i_file_db::file_info> override;
[[nodiscard]] auto [[nodiscard]] auto get_source_path(const std::string &api_path,
get_source_path(const std::string &api_path, std::string &source_path) const
std::string &source_path) const -> api_error override; -> api_error override;
[[nodiscard]] auto [[nodiscard]] auto remove_item(const std::string &api_path)
remove_item(const std::string &api_path) -> api_error override; -> api_error override;
}; };
} // namespace repertory } // namespace repertory

View File

@@ -80,6 +80,10 @@ private:
public: public:
void clear() override; void clear() override;
void enumerate_api_path_list(
std::function<void(const std::vector<std::string> &)> callback,
stop_type &stop_requested) const override;
[[nodiscard]] auto get_api_path(const std::string &source_path, [[nodiscard]] auto get_api_path(const std::string &source_path,
std::string &api_path) const std::string &api_path) const
-> api_error override; -> api_error override;

View File

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

View File

@@ -50,6 +50,10 @@ private:
public: public:
void clear() override; void clear() override;
void enumerate_api_path_list(
std::function<void(const std::vector<std::string> &)> callback,
stop_type &stop_requested) const override;
[[nodiscard]] auto get_api_path(const std::string &source_path, [[nodiscard]] auto get_api_path(const std::string &source_path,
std::string &api_path) const std::string &api_path) const
-> api_error override; -> api_error override;

View File

@@ -42,8 +42,8 @@ public:
direct_open_file(const direct_open_file &) noexcept = delete; direct_open_file(const direct_open_file &) noexcept = delete;
direct_open_file(direct_open_file &&) noexcept = delete; direct_open_file(direct_open_file &&) noexcept = delete;
auto operator=(direct_open_file &&) noexcept -> direct_open_file & = delete; auto operator=(direct_open_file &&) noexcept -> direct_open_file & = delete;
auto auto operator=(const direct_open_file &) noexcept
operator=(const direct_open_file &) noexcept -> direct_open_file & = delete; -> direct_open_file & = delete;
private: private:
std::array<data_buffer, min_ring_size> ring_data_; std::array<data_buffer, min_ring_size> ring_data_;
@@ -51,22 +51,26 @@ private:
protected: protected:
[[nodiscard]] auto on_check_start() -> bool override; [[nodiscard]] auto on_check_start() -> bool override;
[[nodiscard]] auto [[nodiscard]] auto on_chunk_downloaded(std::size_t /* chunk */,
on_chunk_downloaded(std::size_t /* chunk */, const data_buffer & /* buffer */)
const data_buffer & /* buffer */) -> api_error override { -> api_error override {
return api_error::success; return api_error::success;
} }
[[nodiscard]] auto [[nodiscard]] auto on_read_chunk(std::size_t chunk, std::size_t read_size,
on_read_chunk(std::size_t chunk, std::size_t read_size,
std::uint64_t read_offset, data_buffer &data, std::uint64_t read_offset, data_buffer &data,
std::size_t &bytes_read) -> api_error override; std::size_t &bytes_read)
-> api_error override;
[[nodiscard]] auto use_buffer(std::size_t chunk, [[nodiscard]] auto use_buffer(std::size_t chunk,
std::function<api_error(data_buffer &)> func) std::function<api_error(data_buffer &)> func)
-> api_error override; -> api_error override;
public: public:
[[nodiscard]] auto get_source_path() const -> std::string override {
return "direct";
}
[[nodiscard]] auto native_operation(native_operation_callback /* callback */) [[nodiscard]] auto native_operation(native_operation_callback /* callback */)
-> api_error override { -> api_error override {
return api_error::not_supported; return api_error::not_supported;

View File

@@ -53,19 +53,19 @@ private:
i_file_manager *fm_{}; i_file_manager *fm_{};
private: private:
void add_all_items(const stop_type &stop_requested); void add_all_items(stop_type &stop_requested);
void process_removed_directories(std::deque<removed_item> removed_list, void process_removed_directories(std::deque<removed_item> removed_list,
const stop_type &stop_requested); stop_type &stop_requested);
void process_removed_files(std::deque<removed_item> removed_list, void process_removed_files(std::deque<removed_item> removed_list,
const stop_type &stop_requested); stop_type &stop_requested);
void process_removed_items(const stop_type &stop_requested); void process_removed_items(stop_type &stop_requested);
void remove_deleted_items(const stop_type &stop_requested); void remove_deleted_items(stop_type &stop_requested);
void remove_unmatched_source_files(const stop_type &stop_requested); void remove_unmatched_source_files(stop_type &stop_requested);
protected: protected:
[[nodiscard]] static auto create_api_file(std::string path, std::string key, [[nodiscard]] static auto create_api_file(std::string path, std::string key,

View File

@@ -82,7 +82,7 @@ private:
const encrypt_config &cfg, const encrypt_config &cfg,
std::string &api_path) const -> bool; std::string &api_path) const -> bool;
void remove_deleted_files(const stop_type &stop_requested); void remove_deleted_files(stop_type &stop_requested);
public: public:
[[nodiscard]] auto create_directory(const std::string &api_path, [[nodiscard]] auto create_directory(const std::string &api_path,

View File

@@ -54,6 +54,10 @@ private:
const std::string &object_name) const const std::string &object_name) const
-> api_error; -> api_error;
[[nodiscard]] auto
create_directory_object(const std::string &api_path,
const std::string &object_name) const -> api_error;
[[nodiscard]] auto create_directory_paths(const std::string &api_path, [[nodiscard]] auto create_directory_paths(const std::string &api_path,
const std::string &key) const const std::string &key) const
-> api_error; -> api_error;
@@ -85,6 +89,9 @@ private:
return s3_config_; return s3_config_;
} }
[[nodiscard]] auto set_meta_key(const std::string &api_path,
api_meta_map &meta) -> api_error;
protected: protected:
[[nodiscard]] auto create_directory_impl(const std::string &api_path, [[nodiscard]] auto create_directory_impl(const std::string &api_path,
api_meta_map &meta) api_meta_map &meta)

View File

@@ -40,7 +40,7 @@ public:
struct polling_item final { struct polling_item final {
std::string name; std::string name;
frequency freq; frequency freq;
std::function<void(const stop_type &stop_requested)> action; std::function<void(stop_type &stop_requested)> action;
}; };
public: public:

View File

@@ -30,7 +30,7 @@ class app_config;
class tasks final { class tasks final {
public: public:
struct task final { struct task final {
std::function<void(const stop_type &task_stopped)> action; std::function<void(stop_type &task_stopped)> action;
}; };
class i_task { class i_task {

View File

@@ -149,6 +149,50 @@ auto rdb_file_db::count() const -> std::uint64_t {
return ret; return ret;
} }
void rdb_file_db::enumerate_item_list(
std::function<void(const std::vector<i_file_db::file_info> &)> callback,
stop_type &stop_requested) const {
std::vector<i_file_db::file_info> list;
{
auto iter = create_iterator(file_family_);
for (iter->SeekToFirst(); not stop_requested && iter->Valid();
iter->Next()) {
auto json_data = json::parse(iter->value().ToString());
list.emplace_back(i_file_db::file_info{
iter->key().ToString(),
false,
json_data.at("source_path").get<std::string>(),
});
if (list.size() < 100U) {
continue;
}
callback(list);
list.clear();
}
}
{
auto iter = create_iterator(directory_family_);
for (iter->SeekToFirst(); not stop_requested && iter->Valid();
iter->Next()) {
list.emplace_back(i_file_db::file_info{
iter->key().ToString(),
true,
iter->value().ToString(),
});
if (list.size() < 100U) {
continue;
}
callback(list);
list.clear();
}
}
}
auto rdb_file_db::get_api_path(const std::string &source_path, auto rdb_file_db::get_api_path(const std::string &source_path,
std::string &api_path) const -> api_error { std::string &api_path) const -> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
@@ -159,8 +203,9 @@ auto rdb_file_db::get_api_path(const std::string &source_path,
}); });
} }
auto rdb_file_db::get_directory_api_path( auto rdb_file_db::get_directory_api_path(const std::string &source_path,
const std::string &source_path, std::string &api_path) const -> api_error { std::string &api_path) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
auto result = perform_action(function_name, [&]() -> rocksdb::Status { auto result = perform_action(function_name, [&]() -> rocksdb::Status {
@@ -183,8 +228,9 @@ auto rdb_file_db::get_directory_api_path(
: result; : result;
} }
auto rdb_file_db::get_directory_source_path( auto rdb_file_db::get_directory_source_path(const std::string &api_path,
const std::string &api_path, std::string &source_path) const -> api_error { std::string &source_path) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
auto result = perform_action(function_name, [&]() -> rocksdb::Status { auto result = perform_action(function_name, [&]() -> rocksdb::Status {
@@ -245,8 +291,9 @@ auto rdb_file_db::get_file_data(const std::string &api_path,
return result; return result;
} }
auto rdb_file_db::get_file_source_path( auto rdb_file_db::get_file_source_path(const std::string &api_path,
const std::string &api_path, std::string &source_path) const -> api_error { std::string &source_path) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
auto result = perform_action(function_name, [&]() -> rocksdb::Status { auto result = perform_action(function_name, [&]() -> rocksdb::Status {
@@ -264,11 +311,13 @@ auto rdb_file_db::get_file_source_path(
return result; return result;
} }
auto rdb_file_db::get_item_list() const -> std::vector<i_file_db::file_info> { auto rdb_file_db::get_item_list(stop_type &stop_requested) const
-> std::vector<i_file_db::file_info> {
std::vector<i_file_db::file_info> ret{}; std::vector<i_file_db::file_info> ret{};
{ {
auto iter = create_iterator(directory_family_); auto iter = create_iterator(directory_family_);
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { for (iter->SeekToFirst(); not stop_requested && iter->Valid();
iter->Next()) {
ret.emplace_back(i_file_db::file_info{ ret.emplace_back(i_file_db::file_info{
iter->key().ToString(), iter->key().ToString(),
true, true,
@@ -279,11 +328,12 @@ auto rdb_file_db::get_item_list() const -> std::vector<i_file_db::file_info> {
{ {
auto iter = create_iterator(file_family_); auto iter = create_iterator(file_family_);
for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { for (iter->SeekToFirst(); not stop_requested && iter->Valid();
iter->Next()) {
auto json_data = json::parse(iter->value().ToString()); auto json_data = json::parse(iter->value().ToString());
ret.emplace_back(i_file_db::file_info{ ret.emplace_back(i_file_db::file_info{
iter->key().ToString(), iter->key().ToString(),
true, false,
json_data.at("source_path").get<std::string>(), json_data.at("source_path").get<std::string>(),
}); });
} }

View File

@@ -64,6 +64,24 @@ auto rdb_meta_db::create_iterator(rocksdb::ColumnFamilyHandle *family) const
db_->NewIterator(rocksdb::ReadOptions{}, family)); db_->NewIterator(rocksdb::ReadOptions{}, family));
} }
void rdb_meta_db::enumerate_api_path_list(
std::function<void(const std::vector<std::string> &)> callback,
stop_type &stop_requested) const {
std::vector<std::string> list{};
auto iter = create_iterator(meta_family_);
for (iter->SeekToFirst(); not stop_requested && iter->Valid(); iter->Next()) {
list.push_back(iter->key().ToString());
if (list.size() < 100U) {
continue;
}
callback(list);
list.clear();
}
}
auto rdb_meta_db::get_api_path(const std::string &source_path, auto rdb_meta_db::get_api_path(const std::string &source_path,
std::string &api_path) const -> api_error { std::string &api_path) const -> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();

View File

@@ -133,6 +133,33 @@ auto sqlite_file_db::count() const -> std::uint64_t {
return 0U; return 0U;
} }
void sqlite_file_db::enumerate_item_list(
std::function<void(const std::vector<i_file_db::file_info> &)> callback,
stop_type &stop_requested) 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()) {
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{
.api_path = row->get_column("api_path").get_value<std::string>(),
.directory =
row->get_column("directory").get_value<std::int64_t>() == 1,
.source_path =
row->get_column("source_path").get_value<std::string>(),
});
if (list.size() < 100U) {
continue;
}
callback(list);
list.clear();
}
}
}
auto sqlite_file_db::get_api_path(const std::string &source_path, auto sqlite_file_db::get_api_path(const std::string &source_path,
std::string &api_path) const -> api_error { std::string &api_path) const -> api_error {
auto result = utils::db::sqlite::db_select{*db_, file_table} auto result = utils::db::sqlite::db_select{*db_, file_table}
@@ -282,22 +309,22 @@ auto sqlite_file_db::get_file_source_path(const std::string &api_path,
return api_error::item_not_found; return api_error::item_not_found;
} }
auto sqlite_file_db::get_item_list() const auto sqlite_file_db::get_item_list(stop_type &stop_requested) const
-> std::vector<i_file_db::file_info> { -> std::vector<i_file_db::file_info> {
std::vector<i_file_db::file_info> ret; std::vector<i_file_db::file_info> ret;
auto result = utils::db::sqlite::db_select{*db_, file_table}.go(); auto result = utils::db::sqlite::db_select{*db_, file_table}.go();
while (result.has_row()) { while (not stop_requested && result.has_row()) {
std::optional<utils::db::sqlite::db_result::row> row; std::optional<utils::db::sqlite::db_result::row> row;
if (result.get_row(row) && row.has_value()) { if (result.get_row(row) && row.has_value()) {
ret.emplace_back(i_file_db::file_info{ ret.emplace_back(i_file_db::file_info{
row->get_column("api_path").get_value<std::string>(), .api_path = row->get_column("api_path").get_value<std::string>(),
.directory =
row->get_column("directory").get_value<std::int64_t>() == 1, row->get_column("directory").get_value<std::int64_t>() == 1,
.source_path =
row->get_column("source_path").get_value<std::string>(), row->get_column("source_path").get_value<std::string>(),
}); });
} }
result.next_row();
} }
return ret; return ret;

View File

@@ -75,6 +75,28 @@ void sqlite_meta_db::clear() {
std::to_string(result.get_error())); std::to_string(result.get_error()));
} }
void sqlite_meta_db::enumerate_api_path_list(
std::function<void(const std::vector<std::string> &)> callback,
stop_type &stop_requested) 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()) {
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>());
if (list.size() < 100U) {
continue;
}
callback(list);
list.clear();
}
}
}
auto sqlite_meta_db::get_api_path(const std::string &source_path, auto sqlite_meta_db::get_api_path(const std::string &source_path,
std::string &api_path) const -> api_error { std::string &api_path) const -> api_error {
auto result = utils::db::sqlite::db_select{*db_, table_name} auto result = utils::db::sqlite::db_select{*db_, table_name}

View File

@@ -30,7 +30,6 @@
#include "utils/file_utils.hpp" #include "utils/file_utils.hpp"
#include "utils/time.hpp" #include "utils/time.hpp"
#include "utils/utils.hpp" #include "utils/utils.hpp"
#include <spdlog/fmt/bundled/base.h>
namespace repertory { namespace repertory {
auto eviction::check_minimum_requirements(const std::string &file_path) auto eviction::check_minimum_requirements(const std::string &file_path)

View File

@@ -118,8 +118,8 @@ auto fuse_base::chflags_(const char *path, uint32_t flags) -> int {
#endif // __APPLE__ #endif // __APPLE__
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
auto fuse_base::chmod_(const char *path, mode_t mode, auto fuse_base::chmod_(const char *path, mode_t mode, struct fuse_file_info *fi)
struct fuse_file_info *fi) -> int { -> int {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
return instance().execute_callback( return instance().execute_callback(
@@ -334,8 +334,8 @@ auto fuse_base::getxtimes_(const char *path, struct timespec *bkuptime,
#endif // __APPLE__ #endif // __APPLE__
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
auto fuse_base::init_(struct fuse_conn_info *conn, auto fuse_base::init_(struct fuse_conn_info *conn, struct fuse_config *cfg)
struct fuse_config *cfg) -> void * { -> void * {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
return execute_void_pointer_callback(function_name, [&]() -> void * { return execute_void_pointer_callback(function_name, [&]() -> void * {
@@ -477,8 +477,8 @@ auto fuse_base::read_(const char *path, char *buffer, size_t read_size,
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
auto fuse_base::readdir_(const char *path, void *buf, auto fuse_base::readdir_(const char *path, void *buf,
fuse_fill_dir_t fuse_fill_dir, off_t offset, fuse_fill_dir_t fuse_fill_dir, off_t offset,
struct fuse_file_info *fi, struct fuse_file_info *fi, fuse_readdir_flags flags)
fuse_readdir_flags flags) -> int { -> int {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
return instance().execute_callback( return instance().execute_callback(
@@ -510,8 +510,8 @@ auto fuse_base::release_(const char *path, struct fuse_file_info *fi) -> int {
}); });
} }
auto fuse_base::releasedir_(const char *path, auto fuse_base::releasedir_(const char *path, struct fuse_file_info *fi)
struct fuse_file_info *fi) -> int { -> int {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
return instance().execute_callback( return instance().execute_callback(
@@ -521,8 +521,8 @@ auto fuse_base::releasedir_(const char *path,
} }
#if FUSE_USE_VERSION >= 30 #if FUSE_USE_VERSION >= 30
auto fuse_base::rename_(const char *from, const char *to, auto fuse_base::rename_(const char *from, const char *to, unsigned int flags)
unsigned int flags) -> int { -> int {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
return instance().execute_callback( return instance().execute_callback(
@@ -603,7 +603,7 @@ auto fuse_base::listxattr_(const char *path, char *buffer, size_t size) -> int {
void fuse_base::notify_fuse_args_parsed(const std::vector<std::string> &args) { void fuse_base::notify_fuse_args_parsed(const std::vector<std::string> &args) {
event_system::instance().raise<fuse_args_parsed>(std::accumulate( event_system::instance().raise<fuse_args_parsed>(std::accumulate(
args.begin(), args.end(), std::string(), args.begin(), args.end(), std::string(),
[](std::string command_line, const auto &arg) { [](auto &&command_line, auto &&arg) -> auto {
command_line += (command_line.empty() ? arg : (" " + std::string(arg))); command_line += (command_line.empty() ? arg : (" " + std::string(arg)));
return command_line; return command_line;
})); }));
@@ -765,8 +765,8 @@ auto fuse_base::setattr_x_(const char *path, struct setattr_x *attr) -> int {
}); });
} }
auto fuse_base::setbkuptime_(const char *path, auto fuse_base::setbkuptime_(const char *path, const struct timespec *bkuptime)
const struct timespec *bkuptime) -> int { -> int {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
return instance().execute_callback( return instance().execute_callback(
@@ -775,8 +775,8 @@ auto fuse_base::setbkuptime_(const char *path,
}); });
} }
auto fuse_base::setchgtime_(const char *path, auto fuse_base::setchgtime_(const char *path, const struct timespec *chgtime)
const struct timespec *chgtime) -> int { -> int {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
return instance().execute_callback( return instance().execute_callback(
@@ -785,8 +785,8 @@ auto fuse_base::setchgtime_(const char *path,
}); });
} }
auto fuse_base::setcrtime_(const char *path, auto fuse_base::setcrtime_(const char *path, const struct timespec *crtime)
const struct timespec *crtime) -> int { -> int {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
return instance().execute_callback( return instance().execute_callback(

View File

@@ -42,7 +42,7 @@ void remote_open_file_table::close_all(const std::string &client_id) {
auto compat_handles = auto compat_handles =
std::accumulate(compat_file_lookup_.begin(), compat_file_lookup_.end(), std::accumulate(compat_file_lookup_.begin(), compat_file_lookup_.end(),
std::vector<remote::file_handle>(), std::vector<remote::file_handle>(),
[&client_id](auto &&list, auto &&value) { [&client_id](auto &&list, auto &&value) -> auto {
auto &&op_info = value.second; auto &&op_info = value.second;
if (op_info->client_id == client_id) { if (op_info->client_id == client_id) {
list.insert(list.end(), op_info->handles.begin(), list.insert(list.end(), op_info->handles.begin(),
@@ -54,7 +54,7 @@ void remote_open_file_table::close_all(const std::string &client_id) {
auto handles = std::accumulate( auto handles = std::accumulate(
file_lookup_.begin(), file_lookup_.end(), std::vector<native_handle>(), file_lookup_.begin(), file_lookup_.end(), std::vector<native_handle>(),
[&client_id](auto &&list, auto &&value) { [&client_id](auto &&list, auto &&value) -> auto {
auto &&op_info = value.second; auto &&op_info = value.second;
if (op_info->client_id == client_id) { if (op_info->client_id == client_id) {
list.insert(list.end(), op_info->handles.begin(), list.insert(list.end(), op_info->handles.begin(),
@@ -161,10 +161,10 @@ auto remote_open_file_table::has_compat_open_info(
void remote_open_file_table::remove_all(const std::string &file_path) { void remote_open_file_table::remove_all(const std::string &file_path) {
unique_recur_mutex_lock lock(file_mutex_); unique_recur_mutex_lock lock(file_mutex_);
auto compat_open_list = std::accumulate( auto compat_open_list =
compat_file_lookup_.begin(), compat_file_lookup_.end(), std::accumulate(compat_file_lookup_.begin(), compat_file_lookup_.end(),
std::vector<remote::file_handle>(), std::vector<remote::file_handle>(),
[&file_path](auto &&list, auto &&kv) -> std::vector<remote::file_handle> { [&file_path](auto &&list, auto &&kv) -> auto {
if (kv.first == file_path) { if (kv.first == file_path) {
auto *op_info = kv.second.get(); auto *op_info = kv.second.get();
list.insert(list.end(), op_info->handles.begin(), list.insert(list.end(), op_info->handles.begin(),
@@ -175,7 +175,7 @@ void remote_open_file_table::remove_all(const std::string &file_path) {
auto open_list = std::accumulate( auto open_list = std::accumulate(
file_lookup_.begin(), file_lookup_.end(), std::vector<native_handle>(), file_lookup_.begin(), file_lookup_.end(), std::vector<native_handle>(),
[&file_path](auto &&list, auto &&kv) -> std::vector<native_handle> { [&file_path](auto &&list, auto &&kv) -> auto {
if (kv.first == file_path) { if (kv.first == file_path) {
auto *op_info = kv.second.get(); auto *op_info = kv.second.get();
list.insert(list.end(), op_info->handles.begin(), list.insert(list.end(), op_info->handles.begin(),

View File

@@ -97,7 +97,7 @@ void file_manager::close_timed_out_files() {
auto closeable_list = auto closeable_list =
std::accumulate(open_file_lookup_.begin(), open_file_lookup_.end(), std::accumulate(open_file_lookup_.begin(), open_file_lookup_.end(),
std::vector<std::shared_ptr<i_closeable_open_file>>{}, std::vector<std::shared_ptr<i_closeable_open_file>>{},
[](auto items, const auto &item) -> auto { [](auto &&items, auto &&item) -> auto {
if (item.second->get_open_file_count() == 0U && if (item.second->get_open_file_count() == 0U &&
item.second->can_close()) { item.second->can_close()) {
items.push_back(item.second); items.push_back(item.second);
@@ -235,6 +235,10 @@ auto file_manager::get_open_file_count(const std::string &api_path) const
auto file_manager::get_open_file(std::uint64_t handle, bool write_supported, auto file_manager::get_open_file(std::uint64_t handle, bool write_supported,
std::shared_ptr<i_open_file> &file) -> bool { std::shared_ptr<i_open_file> &file) -> bool {
if (write_supported && provider_.is_read_only()) {
return false;
}
unique_recur_mutex_lock open_lock(open_file_mtx_); unique_recur_mutex_lock open_lock(open_file_mtx_);
auto file_ptr = get_open_file_by_handle(handle); auto file_ptr = get_open_file_by_handle(handle);
if (not file_ptr) { if (not file_ptr) {
@@ -265,21 +269,20 @@ auto file_manager::get_open_file_count() const -> std::size_t {
auto file_manager::get_open_files() const auto file_manager::get_open_files() const
-> std::unordered_map<std::string, std::size_t> { -> std::unordered_map<std::string, std::size_t> {
std::unordered_map<std::string, std::size_t> ret;
recur_mutex_lock open_lock(open_file_mtx_); recur_mutex_lock open_lock(open_file_mtx_);
for (const auto &item : open_file_lookup_) { return std::accumulate(open_file_lookup_.begin(), open_file_lookup_.end(),
ret[item.first] = item.second->get_open_file_count(); std::unordered_map<std::string, std::size_t>{},
} [](auto &&map, auto &&item) -> auto {
map[item.first] = item.second->get_open_file_count();
return ret; return map;
});
} }
auto file_manager::get_open_handle_count() const -> std::size_t { auto file_manager::get_open_handle_count() const -> std::size_t {
recur_mutex_lock open_lock(open_file_mtx_); recur_mutex_lock open_lock(open_file_mtx_);
return std::accumulate( return std::accumulate(open_file_lookup_.begin(), open_file_lookup_.end(),
open_file_lookup_.begin(), open_file_lookup_.end(), std::size_t(0U), std::size_t(0U),
[](std::size_t count, const auto &item) -> std::size_t { [](auto &&count, auto &&item) -> auto {
return count + item.second->get_open_file_count(); return count + item.second->get_open_file_count();
}); });
} }
@@ -380,10 +383,11 @@ auto file_manager::open(const std::string &api_path, bool directory,
return open(api_path, directory, ofd, handle, file, nullptr); return open(api_path, directory, ofd, handle, file, nullptr);
} }
auto file_manager::open( auto file_manager::open(const std::string &api_path, bool directory,
const std::string &api_path, bool directory, const open_file_data &ofd, const open_file_data &ofd, std::uint64_t &handle,
std::uint64_t &handle, std::shared_ptr<i_open_file> &file, std::shared_ptr<i_open_file> &file,
std::shared_ptr<i_closeable_open_file> closeable_file) -> api_error { std::shared_ptr<i_closeable_open_file> closeable_file)
-> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
const auto create_and_add_handle = const auto create_and_add_handle =
@@ -435,6 +439,10 @@ auto file_manager::open(
auto ring_size{ring_buffer_file_size / chunk_size}; auto ring_size{ring_buffer_file_size / chunk_size};
const auto get_download_type = [&](download_type type) -> download_type { const auto get_download_type = [&](download_type type) -> download_type {
if (not directory && provider_.is_read_only()) {
return download_type::direct;
}
if (directory || fsi.size == 0U || is_processing(api_path)) { if (directory || fsi.size == 0U || is_processing(api_path)) {
return download_type::default_; return download_type::default_;
} }
@@ -747,8 +755,8 @@ auto file_manager::rename_directory(const std::string &from_api_path,
} }
auto file_manager::rename_file(const std::string &from_api_path, auto file_manager::rename_file(const std::string &from_api_path,
const std::string &to_api_path, const std::string &to_api_path, bool overwrite)
bool overwrite) -> api_error { -> api_error {
if (not provider_.is_rename_supported()) { if (not provider_.is_rename_supported()) {
return api_error::not_implemented; return api_error::not_implemented;
} }

View File

@@ -150,16 +150,16 @@ auto lock_data::set_mount_state(bool active, const std::string &mount_location,
(mount_state[mount_id]["Location"].get<std::string>() != (mount_state[mount_id]["Location"].get<std::string>() !=
mount_location)))) { mount_location)))) {
const auto lines = utils::file::read_file_lines(get_lock_data_file()); const auto lines = utils::file::read_file_lines(get_lock_data_file());
const auto txt = const auto txt = std::accumulate(
std::accumulate(lines.begin(), lines.end(), std::string(), lines.begin(), lines.end(), std::string(),
[](std::string s, const std::string &s2) { [](auto &&lines, auto &&line) -> auto { return lines + line; });
return std::move(s) + s2; auto json_data = json::parse(txt.empty() ? "{}" : txt);
}); json_data[mount_id] = {
auto json = json::parse(txt.empty() ? "{}" : txt); {"Active", active},
json[mount_id] = {{"Active", active},
{"Location", active ? mount_location : ""}, {"Location", active ? mount_location : ""},
{"PID", active ? pid : -1}}; {"PID", active ? pid : -1},
ret = utils::file::write_json_file(get_lock_data_file(), json); };
ret = utils::file::write_json_file(get_lock_data_file(), json_data);
} else { } else {
ret = true; ret = true;
} }

View File

@@ -36,7 +36,7 @@
#include "utils/time.hpp" #include "utils/time.hpp"
namespace repertory { namespace repertory {
void base_provider::add_all_items(const stop_type &stop_requested) { void base_provider::add_all_items(stop_type &stop_requested) {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
api_file_list list{}; api_file_list list{};
@@ -140,6 +140,7 @@ auto base_provider::create_directory(const std::string &api_path,
api_meta_map &meta) -> api_error { api_meta_map &meta) -> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
try {
bool exists{}; bool exists{};
auto res = is_directory(api_path, exists); auto res = is_directory(api_path, exists);
if (res != api_error::success) { if (res != api_error::success) {
@@ -165,27 +166,28 @@ auto base_provider::create_directory(const std::string &api_path,
return api_error::item_exists; return api_error::item_exists;
} }
try {
res = create_directory_impl(api_path, meta); res = create_directory_impl(api_path, meta);
if (res != api_error::success) { if (res != api_error::success) {
utils::error::raise_api_path_error(function_name, api_path, res, utils::error::raise_api_path_error(function_name, api_path, res,
"failed to create directory"); "failed to create directory");
return res; return res;
} }
} catch (const std::exception &e) {
utils::error::raise_api_path_error(function_name, api_path, e,
"failed to create directory");
return api_error::error;
}
meta[META_DIRECTORY] = utils::string::from_bool(true); meta[META_DIRECTORY] = utils::string::from_bool(true);
return set_item_meta(api_path, meta); return set_item_meta(api_path, meta);
} catch (const std::exception &e) {
utils::error::raise_api_path_error(function_name, api_path, e,
"failed to create directory");
}
return api_error::error;
} }
auto base_provider::create_file(const std::string &api_path, api_meta_map &meta) auto base_provider::create_file(const std::string &api_path, api_meta_map &meta)
-> api_error { -> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
try {
bool exists{}; bool exists{};
auto res = is_directory(api_path, exists); auto res = is_directory(api_path, exists);
if (res != api_error::success && res != api_error::item_not_found) { if (res != api_error::success && res != api_error::item_not_found) {
@@ -209,7 +211,6 @@ auto base_provider::create_file(const std::string &api_path, api_meta_map &meta)
return api_error::item_exists; return api_error::item_exists;
} }
try {
res = create_file_extra(api_path, meta); res = create_file_extra(api_path, meta);
if (res != api_error::success) { if (res != api_error::success) {
utils::error::raise_api_path_error(function_name, api_path, res, utils::error::raise_api_path_error(function_name, api_path, res,
@@ -260,6 +261,7 @@ auto base_provider::get_directory_items(const std::string &api_path,
-> api_error { -> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
try {
bool exists{}; bool exists{};
auto res = is_directory(api_path, exists); auto res = is_directory(api_path, exists);
if (res != api_error::success) { if (res != api_error::success) {
@@ -269,7 +271,6 @@ auto base_provider::get_directory_items(const std::string &api_path,
return api_error::directory_not_found; return api_error::directory_not_found;
} }
try {
res = get_directory_items_impl(api_path, list); res = get_directory_items_impl(api_path, list);
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
@@ -436,7 +437,7 @@ auto base_provider::is_file_writeable(const std::string &api_path) const
} }
void base_provider::process_removed_directories( void base_provider::process_removed_directories(
std::deque<removed_item> removed_list, const stop_type &stop_requested) { std::deque<removed_item> removed_list, stop_type &stop_requested) {
for (const auto &item : removed_list) { for (const auto &item : removed_list) {
if (stop_requested) { if (stop_requested) {
return; return;
@@ -453,7 +454,7 @@ void base_provider::process_removed_directories(
} }
void base_provider::process_removed_files(std::deque<removed_item> removed_list, void base_provider::process_removed_files(std::deque<removed_item> removed_list,
const stop_type &stop_requested) { stop_type &stop_requested) {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
auto orphaned_directory = auto orphaned_directory =
@@ -512,8 +513,9 @@ void base_provider::process_removed_files(std::deque<removed_item> removed_list,
} }
} }
void base_provider::process_removed_items(const stop_type &stop_requested) { void base_provider::process_removed_items(stop_type &stop_requested) {
auto list = db3_->get_api_path_list(); db3_->enumerate_api_path_list(
[this, &stop_requested](auto &&list) {
[[maybe_unused]] auto res = [[maybe_unused]] auto res =
std::all_of(list.begin(), list.end(), [&](auto &&api_path) -> bool { std::all_of(list.begin(), list.end(), [&](auto &&api_path) -> bool {
if (stop_requested) { if (stop_requested) {
@@ -528,25 +530,24 @@ void base_provider::process_removed_items(const stop_type &stop_requested) {
} }
if (utils::string::to_bool(meta[META_DIRECTORY])) { if (utils::string::to_bool(meta[META_DIRECTORY])) {
bool exists{};
if (is_directory(api_path, exists) !=
api_error::success) {
return;
}
if (exists) {
return;
}
process_removed_directories(
{
removed_item{api_path, true, ""},
},
task_stopped);
return; return;
} }
// bool exists{};
// if (is_directory(api_path, exists) != api_error::success) {
// return;
// }
//
// if (exists) {
// return;
// }
//
// // process_removed_directories(
// // {
// // removed_item{api_path, true, ""},
// // },
// // stop_requested2);
//
// return;
// }
bool exists{}; bool exists{};
if (is_file(api_path, exists) != api_error::success) { if (is_file(api_path, exists) != api_error::success) {
@@ -567,9 +568,11 @@ void base_provider::process_removed_items(const stop_type &stop_requested) {
return not stop_requested; return not stop_requested;
}); });
},
stop_requested);
} }
void base_provider::remove_deleted_items(const stop_type &stop_requested) { void base_provider::remove_deleted_items(stop_type &stop_requested) {
add_all_items(stop_requested); add_all_items(stop_requested);
if (stop_requested) { if (stop_requested) {
return; return;
@@ -665,8 +668,7 @@ auto base_provider::remove_item_meta(const std::string &api_path,
return db3_->remove_item_meta(api_path, key); return db3_->remove_item_meta(api_path, key);
} }
void base_provider::remove_unmatched_source_files( void base_provider::remove_unmatched_source_files(stop_type &stop_requested) {
const stop_type &stop_requested) {
if (is_read_only()) { if (is_read_only()) {
return; return;
} }
@@ -783,8 +785,6 @@ auto base_provider::upload_file(const std::string &api_path,
stop_type &stop_requested) -> api_error { stop_type &stop_requested) -> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
event_system::instance().raise<provider_upload_begin>(api_path, source_path);
const auto notify_end = [&api_path, const auto notify_end = [&api_path,
&source_path](api_error error) -> api_error { &source_path](api_error error) -> api_error {
event_system::instance().raise<provider_upload_end>(api_path, source_path, event_system::instance().raise<provider_upload_end>(api_path, source_path,
@@ -793,6 +793,9 @@ auto base_provider::upload_file(const std::string &api_path,
}; };
try { try {
event_system::instance().raise<provider_upload_begin>(api_path,
source_path);
return notify_end(upload_file_impl(api_path, source_path, stop_requested)); return notify_end(upload_file_impl(api_path, source_path, stop_requested));
} catch (const std::exception &e) { } catch (const std::exception &e) {
utils::error::raise_error(function_name, e, "exception occurred"); utils::error::raise_error(function_name, e, "exception occurred");

View File

@@ -33,15 +33,17 @@
#include "utils/file_utils.hpp" #include "utils/file_utils.hpp"
#include "utils/path.hpp" #include "utils/path.hpp"
#include "utils/polling.hpp" #include "utils/polling.hpp"
#include <utils/config.hpp>
namespace repertory { namespace repertory {
encrypt_provider::encrypt_provider(app_config &config) encrypt_provider::encrypt_provider(app_config &config)
: config_(config), encrypt_config_(config.get_encrypt_config()) {} : config_(config), encrypt_config_(config.get_encrypt_config()) {}
auto encrypt_provider::create_api_file( auto encrypt_provider::create_api_file(const std::string &api_path,
const std::string &api_path, bool directory, bool directory,
const std::string &source_path) -> api_file { const std::string &source_path)
auto times = utils::file::get_times(source_path); -> api_file {
auto times{utils::file::get_times(source_path)};
if (not times.has_value()) { if (not times.has_value()) {
throw std::runtime_error("failed to get file times"); throw std::runtime_error("failed to get file times");
} }
@@ -112,7 +114,7 @@ auto encrypt_provider::do_fs_operation(
std::function<api_error(const encrypt_config &cfg, std::function<api_error(const encrypt_config &cfg,
const std::string &source_path)> const std::string &source_path)>
callback) const -> api_error { callback) const -> api_error {
const auto &cfg = get_encrypt_config(); const auto &cfg{get_encrypt_config()};
std::string source_path{api_path}; std::string source_path{api_path};
if (api_path != "/" && not utils::encryption::decrypt_file_path( if (api_path != "/" && not utils::encryption::decrypt_file_path(
@@ -129,7 +131,7 @@ auto encrypt_provider::do_fs_operation(
: api_error::item_not_found; : api_error::item_not_found;
} }
auto exists = utils::file::file{source_path}.exists(); auto exists{utils::file::file{source_path}.exists()};
if (exists && directory) { if (exists && directory) {
return api_error::item_exists; return api_error::item_exists;
} }
@@ -149,8 +151,9 @@ auto encrypt_provider::do_fs_operation(
return callback(cfg, source_path); return callback(cfg, source_path);
} }
auto encrypt_provider::get_api_path_from_source( auto encrypt_provider::get_api_path_from_source(const std::string &source_path,
const std::string &source_path, std::string &api_path) const -> api_error { std::string &api_path) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
try { try {
@@ -168,10 +171,10 @@ auto encrypt_provider::get_directory_item_count(
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
std::uint64_t count{}; std::uint64_t count{};
auto res = do_fs_operation( auto res{
api_path, true, do_fs_operation(api_path, true,
[&api_path, &count](const encrypt_config & /* cfg */, [&api_path, &count](auto && /* cfg */,
const std::string &source_path) -> api_error { auto &&source_path) -> api_error {
try { try {
count = utils::file::directory{source_path}.count(); count = utils::file::directory{source_path}.count();
} catch (const std::exception &ex) { } catch (const std::exception &ex) {
@@ -180,7 +183,8 @@ auto encrypt_provider::get_directory_item_count(
"failed to get directory item count"); "failed to get directory item count");
} }
return api_error::success; return api_error::success;
}); }),
};
if (res != api_error::success) { if (res != api_error::success) {
utils::error::raise_api_path_error(function_name, api_path, res, utils::error::raise_api_path_error(function_name, api_path, res,
"failed to get directory item count"); "failed to get directory item count");
@@ -189,22 +193,24 @@ auto encrypt_provider::get_directory_item_count(
return count; return count;
} }
auto encrypt_provider::get_directory_items( auto encrypt_provider::get_directory_items(const std::string &api_path,
const std::string &api_path, directory_item_list &list) const -> api_error { directory_item_list &list) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
return do_fs_operation( return do_fs_operation(
api_path, true, api_path, true,
[this, &list](const encrypt_config &cfg, [this, &list](auto &&cfg, auto &&source_path) -> api_error {
const std::string &source_path) -> api_error {
try { try {
for (const auto &dir_entry : for (const auto &dir_entry :
utils::file::directory{source_path}.get_items()) { utils::file::directory{source_path}.get_items()) {
try { try {
std::string current_api_path; std::string current_api_path;
if (dir_entry->is_directory_item()) { if (dir_entry->is_directory_item()) {
auto result = db_->get_directory_api_path(dir_entry->get_path(), auto result{
current_api_path); db_->get_directory_api_path(dir_entry->get_path(),
current_api_path),
};
if (result != api_error::success && if (result != api_error::success &&
result != api_error::directory_not_found) { result != api_error::directory_not_found) {
// TODO raise error // TODO raise error
@@ -224,8 +230,10 @@ auto encrypt_provider::get_directory_items(
} }
} }
} else { } else {
auto result = db_->get_file_api_path(dir_entry->get_path(), auto result{
current_api_path); db_->get_file_api_path(dir_entry->get_path(),
current_api_path),
};
if (result != api_error::success && if (result != api_error::success &&
result != api_error::item_not_found) { result != api_error::item_not_found) {
// TODO raise error // TODO raise error
@@ -238,9 +246,11 @@ auto encrypt_provider::get_directory_items(
} }
} }
auto file = create_api_file(current_api_path, auto file{
create_api_file(current_api_path,
dir_entry->is_directory_item(), dir_entry->is_directory_item(),
dir_entry->get_path()); dir_entry->get_path()),
};
directory_item dir_item{}; directory_item dir_item{};
dir_item.api_parent = file.api_parent; dir_item.api_parent = file.api_parent;
@@ -294,7 +304,7 @@ auto encrypt_provider::get_file(const std::string &api_path,
try { try {
bool exists{}; bool exists{};
auto res = is_directory(api_path, exists); auto res{is_directory(api_path, exists)};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
@@ -303,7 +313,7 @@ auto encrypt_provider::get_file(const std::string &api_path,
} }
std::string source_path; std::string source_path;
auto result = db_->get_file_source_path(api_path, source_path); auto result{db_->get_file_source_path(api_path, source_path)};
if (result != api_error::success) { if (result != api_error::success) {
return result; return result;
} }
@@ -318,11 +328,12 @@ auto encrypt_provider::get_file(const std::string &api_path,
return api_error::error; return api_error::error;
} }
auto encrypt_provider::get_file_list( auto encrypt_provider::get_file_list(api_file_list &list,
api_file_list &list, std::string & /* marker */) const -> api_error { std::string & /* marker */) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
const auto &cfg = get_encrypt_config(); const auto &cfg{get_encrypt_config()};
try { try {
for (const auto &dir_entry : utils::file::directory{cfg.path}.get_items()) { for (const auto &dir_entry : utils::file::directory{cfg.path}.get_items()) {
@@ -342,13 +353,14 @@ auto encrypt_provider::get_file_list(
return api_error::error; return api_error::error;
} }
auto encrypt_provider::get_file_size( auto encrypt_provider::get_file_size(const std::string &api_path,
const std::string &api_path, std::uint64_t &file_size) const -> api_error { std::uint64_t &file_size) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
try { try {
std::string source_path; std::string source_path;
auto result = db_->get_file_source_path(api_path, source_path); auto result{db_->get_file_source_path(api_path, source_path)};
if (result != api_error::success) { if (result != api_error::success) {
return result; return result;
} }
@@ -364,12 +376,13 @@ auto encrypt_provider::get_file_size(
return api_error::error; return api_error::error;
} }
auto encrypt_provider::get_filesystem_item( auto encrypt_provider::get_filesystem_item(const std::string &api_path,
const std::string &api_path, bool directory, bool directory,
filesystem_item &fsi) const -> api_error { filesystem_item &fsi) const
-> api_error {
std::string source_path; std::string source_path;
if (directory) { if (directory) {
auto result = db_->get_directory_source_path(api_path, source_path); auto result{db_->get_directory_source_path(api_path, source_path)};
if (result != api_error::success) { if (result != api_error::success) {
return result; return result;
} }
@@ -382,7 +395,7 @@ auto encrypt_provider::get_filesystem_item(
return api_error::success; return api_error::success;
} }
auto result = db_->get_file_source_path(api_path, source_path); auto result{db_->get_file_source_path(api_path, source_path)};
if (result != api_error::success) { if (result != api_error::success) {
return result; return result;
} }
@@ -400,7 +413,7 @@ auto encrypt_provider::get_filesystem_item(
auto encrypt_provider::get_filesystem_item_from_source_path( auto encrypt_provider::get_filesystem_item_from_source_path(
const std::string &source_path, filesystem_item &fsi) const -> api_error { const std::string &source_path, filesystem_item &fsi) const -> api_error {
std::string api_path{}; std::string api_path{};
auto res = get_api_path_from_source(source_path, api_path); auto res{get_api_path_from_source(source_path, api_path)};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
@@ -417,14 +430,15 @@ auto encrypt_provider::get_filesystem_item_from_source_path(
return get_filesystem_item(api_path, false, fsi); return get_filesystem_item(api_path, false, fsi);
} }
auto encrypt_provider::get_filesystem_item_and_file( auto encrypt_provider::get_filesystem_item_and_file(const std::string &api_path,
const std::string &api_path, api_file &file, api_file &file,
filesystem_item &fsi) const -> api_error { filesystem_item &fsi) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
try { try {
bool exists{}; bool exists{};
auto res = is_directory(api_path, exists); auto res{is_directory(api_path, exists)};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
@@ -432,7 +446,7 @@ auto encrypt_provider::get_filesystem_item_and_file(
return api_error::directory_exists; return api_error::directory_exists;
} }
auto ret = get_filesystem_item(api_path, exists, fsi); auto ret{get_filesystem_item(api_path, exists, fsi)};
if (ret != api_error::success) { if (ret != api_error::success) {
return ret; return ret;
} }
@@ -457,7 +471,7 @@ auto encrypt_provider::get_item_meta(const std::string &api_path,
try { try {
std::string source_path; std::string source_path;
auto result = db_->get_source_path(api_path, source_path); auto result{db_->get_source_path(api_path, source_path)};
if (result != api_error::success) { if (result != api_error::success) {
return result; return result;
} }
@@ -468,7 +482,7 @@ auto encrypt_provider::get_item_meta(const std::string &api_path,
return result; return result;
} }
auto file = create_api_file(api_path, is_dir, source_path); auto file{create_api_file(api_path, is_dir, source_path)};
create_item_meta(meta, is_dir, file); create_item_meta(meta, is_dir, file);
return api_error::success; return api_error::success;
} catch (const std::exception &ex) { } catch (const std::exception &ex) {
@@ -483,7 +497,7 @@ auto encrypt_provider::get_item_meta(const std::string &api_path,
const std::string &key, const std::string &key,
std::string &value) const -> api_error { std::string &value) const -> api_error {
api_meta_map meta{}; api_meta_map meta{};
auto ret = get_item_meta(api_path, meta); auto ret{get_item_meta(api_path, meta)};
if (ret != api_error::success) { if (ret != api_error::success) {
return ret; return ret;
} }
@@ -511,8 +525,9 @@ auto encrypt_provider::get_total_item_count() const -> std::uint64_t {
} }
auto encrypt_provider::get_used_drive_space() const -> std::uint64_t { auto encrypt_provider::get_used_drive_space() const -> std::uint64_t {
auto free_space = auto free_space{
utils::file::get_free_drive_space(get_encrypt_config().path); utils::file::get_free_drive_space(get_encrypt_config().path),
};
return free_space.has_value() ? get_total_drive_space() - free_space.value() return free_space.has_value() ? get_total_drive_space() - free_space.value()
: 0U; : 0U;
} }
@@ -523,7 +538,7 @@ auto encrypt_provider::is_directory(const std::string &api_path,
try { try {
std::string source_path; std::string source_path;
auto result = db_->get_directory_source_path(api_path, source_path); auto result{db_->get_directory_source_path(api_path, source_path)};
if (result != api_error::success) { if (result != api_error::success) {
if (result != api_error::directory_not_found) { if (result != api_error::directory_not_found) {
@@ -544,13 +559,13 @@ auto encrypt_provider::is_directory(const std::string &api_path,
return api_error::error; return api_error::error;
} }
auto encrypt_provider::is_file(const std::string &api_path, auto encrypt_provider::is_file(const std::string &api_path, bool &exists) const
bool &exists) const -> api_error { -> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
try { try {
std::string source_path; std::string source_path;
auto result = db_->get_file_source_path(api_path, source_path); auto result{db_->get_file_source_path(api_path, source_path)};
if (result != api_error::success) { if (result != api_error::success) {
if (result != api_error::item_not_found) { if (result != api_error::item_not_found) {
return result; return result;
@@ -587,8 +602,10 @@ auto encrypt_provider::process_directory_entry(
try { try {
const auto do_add_directory = const auto do_add_directory =
[this, &cfg](std::string_view dir_path) -> std::string { [this, &cfg](std::string_view dir_path) -> std::string {
auto encrypted_parts = utils::string::split( auto encrypted_parts{
utils::path::create_api_path(dir_path), '/', false); utils::string::split(utils::path::create_api_path(dir_path), '/',
false),
};
for (std::size_t part_idx = 1U; part_idx < encrypted_parts.size(); for (std::size_t part_idx = 1U; part_idx < encrypted_parts.size();
++part_idx) { ++part_idx) {
@@ -611,8 +628,9 @@ auto encrypt_provider::process_directory_entry(
current_source_path = utils::path::combine(current_source_path, {part}); current_source_path = utils::path::combine(current_source_path, {part});
std::string current_api_path{}; std::string current_api_path{};
auto result = auto result{
db_->get_directory_api_path(current_source_path, current_api_path); db_->get_directory_api_path(current_source_path, current_api_path),
};
if (result == api_error::directory_not_found) { if (result == api_error::directory_not_found) {
current_api_path = utils::path::create_api_path( current_api_path = utils::path::create_api_path(
current_encrypted_path + '/' + encrypted_parts.at(current_idx)); current_encrypted_path + '/' + encrypted_parts.at(current_idx));
@@ -652,11 +670,12 @@ auto encrypt_provider::process_directory_entry(
} }
if (dir_entry.is_file_item() && not dir_entry.is_symlink()) { if (dir_entry.is_file_item() && not dir_entry.is_symlink()) {
auto relative_path = auto relative_path{
utils::path::get_relative_path(dir_entry.get_path(), cfg.path); utils::path::get_relative_path(dir_entry.get_path(), cfg.path),
};
i_file_db::file_data data; i_file_db::file_data data;
auto file_res = db_->get_file_data(dir_entry.get_path(), data); auto file_res{db_->get_file_data(dir_entry.get_path(), data)};
if (file_res != api_error::success && if (file_res != api_error::success &&
file_res != api_error::item_not_found) { file_res != api_error::item_not_found) {
// TODO raise error // TODO raise error
@@ -664,8 +683,10 @@ auto encrypt_provider::process_directory_entry(
} }
std::string api_parent{}; std::string api_parent{};
auto parent_res = db_->get_directory_api_path( auto parent_res{
utils::path::get_parent_path(dir_entry.get_path()), api_parent); db_->get_directory_api_path(
utils::path::get_parent_path(dir_entry.get_path()), api_parent),
};
if (parent_res != api_error::success && if (parent_res != api_error::success &&
parent_res != api_error::directory_not_found) { parent_res != api_error::directory_not_found) {
// TODO raise error // TODO raise error
@@ -720,27 +741,28 @@ auto encrypt_provider::read_file_bytes(const std::string &api_path,
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
i_file_db::file_data file_data{}; i_file_db::file_data file_data{};
auto result = db_->get_file_data(api_path, file_data); auto result{db_->get_file_data(api_path, file_data)};
if (result != api_error::success) { if (result != api_error::success) {
return result; return result;
} }
auto opt_size = utils::file::file{file_data.source_path}.size(); auto opt_size{utils::file::file{file_data.source_path}.size()};
if (not opt_size.has_value()) { if (not opt_size.has_value()) {
return api_error::os_error; return api_error::os_error;
} }
auto file_size{opt_size.value()}; auto file_size{opt_size.value()};
const auto &cfg = get_encrypt_config(); const auto &cfg{get_encrypt_config()};
unique_recur_mutex_lock reader_lookup_lock(reader_lookup_mtx_); unique_recur_mutex_lock reader_lookup_lock(reader_lookup_mtx_);
if (file_data.file_size != file_size) { if (file_data.file_size != file_size) {
auto relative_path = auto relative_path{
utils::path::get_relative_path(file_data.source_path, cfg.path); utils::path::get_relative_path(file_data.source_path, cfg.path),
};
auto info = std::make_shared<reader_info>(); auto info{std::make_shared<reader_info>()};
info->reader = std::make_unique<utils::encryption::encrypting_reader>( 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,
cfg.encryption_token, utils::path::get_parent_path(relative_path)); cfg.encryption_token, utils::path::get_parent_path(relative_path));
@@ -758,7 +780,7 @@ auto encrypt_provider::read_file_bytes(const std::string &api_path,
} }
} else if (reader_lookup_.find(file_data.source_path) == } else if (reader_lookup_.find(file_data.source_path) ==
reader_lookup_.end()) { reader_lookup_.end()) {
auto info = std::make_shared<reader_info>(); auto info{std::make_shared<reader_info>()};
info->reader = std::make_unique<utils::encryption::encrypting_reader>( info->reader = std::make_unique<utils::encryption::encrypting_reader>(
api_path, file_data.source_path, stop_requested, cfg.encryption_token, api_path, file_data.source_path, stop_requested, cfg.encryption_token,
std::move(file_data.iv_list)); std::move(file_data.iv_list));
@@ -769,7 +791,7 @@ auto encrypt_provider::read_file_bytes(const std::string &api_path,
return api_error::success; return api_error::success;
} }
auto info = reader_lookup_.at(file_data.source_path); auto info{reader_lookup_.at(file_data.source_path)};
info->last_access_time = std::chrono::system_clock::now(); info->last_access_time = std::chrono::system_clock::now();
reader_lookup_lock.unlock(); reader_lookup_lock.unlock();
@@ -777,27 +799,29 @@ auto encrypt_provider::read_file_bytes(const std::string &api_path,
info->reader->set_read_position(offset); info->reader->set_read_position(offset);
data.resize(size); data.resize(size);
auto res = auto res{
info->reader->reader_function(reinterpret_cast<char *>(data.data()), 1U, info->reader->reader_function(reinterpret_cast<char *>(data.data()), 1U,
data.size(), info->reader.get()); data.size(), info->reader.get()),
if (res == 0) { };
return api_error::os_error; return res == 0 ? api_error::os_error : api_error::success;
} }
return api_error::success; void encrypt_provider::remove_deleted_files(stop_type &stop_requested) {
} REPERTORY_USES_FUNCTION_NAME();
void encrypt_provider::remove_deleted_files(const stop_type &stop_requested) { db_->enumerate_item_list(
[this, &stop_requested](auto &&list) {
std::vector<i_file_db::file_info> removed_list{}; std::vector<i_file_db::file_info> removed_list{};
for (const auto &item : list) {
for (const auto &item : db_->get_item_list()) {
if (stop_requested) { if (stop_requested) {
return; return;
} }
if (not utils::path::exists(item.source_path)) { if (utils::path::exists(item.source_path)) {
removed_list.emplace_back(item); continue;
} }
removed_list.emplace_back(item);
} }
for (const auto &item : removed_list) { for (const auto &item : removed_list) {
@@ -805,17 +829,26 @@ void encrypt_provider::remove_deleted_files(const stop_type &stop_requested) {
return; return;
} }
// TODO handle error auto res{db_->remove_item(item.api_path)};
auto del_res = db_->remove_item(item.api_path); if (res != api_error::success) {
utils::error::raise_api_path_error(
function_name, item.api_path, item.source_path, res,
fmt::format("failed to process externally removed item|dir|{}",
utils::string::from_bool(item.directory)));
continue;
}
if (item.directory) { if (item.directory) {
event_system::instance().raise<directory_removed_externally>( event_system::instance().raise<directory_removed_externally>(
item.api_path, item.source_path); item.api_path, item.source_path);
continue; continue;
} }
event_system::instance().raise<file_removed_externally>(item.api_path, event_system::instance().raise<file_removed_externally>(
item.source_path); item.api_path, item.source_path);
} }
},
stop_requested);
} }
auto encrypt_provider::start(api_item_added_callback /*api_item_added*/, auto encrypt_provider::start(api_item_added_callback /*api_item_added*/,
@@ -829,16 +862,16 @@ auto encrypt_provider::start(api_item_added_callback /*api_item_added*/,
db_ = create_file_db(config_); db_ = create_file_db(config_);
std::string source_path; std::string source_path;
auto result = db_->get_directory_source_path("/", source_path); auto result{db_->get_directory_source_path("/", source_path)};
if (result != api_error::success && if (result != api_error::success &&
result != api_error::directory_not_found) { result != api_error::directory_not_found) {
throw startup_exception( throw startup_exception(
fmt::format("failed to get root|{}", api_error_to_string(result))); fmt::format("failed to get root|{}", api_error_to_string(result)));
} }
auto cfg_path = utils::path::absolute(get_encrypt_config().path); auto cfg_path{utils::path::absolute(get_encrypt_config().path)};
if (result == api_error::success) { if (result == api_error::success) {
auto cur_path = utils::path::absolute(source_path); auto cur_path{utils::path::absolute(source_path)};
#if defined(_WIN32) #if defined(_WIN32)
if (utils::string::to_lower(cur_path) != if (utils::string::to_lower(cur_path) !=
utils::string::to_lower(cfg_path)) { utils::string::to_lower(cfg_path)) {

View File

@@ -40,9 +40,9 @@
#include "utils/time.hpp" #include "utils/time.hpp"
namespace { namespace {
[[nodiscard]] auto [[nodiscard]] auto set_request_path(auto &request,
set_request_path(auto &request, const std::string &object_name)
const std::string &object_name) -> repertory::api_error { -> repertory::api_error {
request.path = object_name; request.path = object_name;
if (request.path.substr(1U).size() > repertory::max_s3_object_name_length) { if (request.path.substr(1U).size() > repertory::max_s3_object_name_length) {
return repertory::api_error::name_too_long; return repertory::api_error::name_too_long;
@@ -56,10 +56,11 @@ namespace repertory {
s3_provider::s3_provider(app_config &config, i_http_comm &comm) s3_provider::s3_provider(app_config &config, i_http_comm &comm)
: base_provider(config, comm) {} : base_provider(config, comm) {}
auto s3_provider::add_if_not_found( auto s3_provider::add_if_not_found(api_file &file,
api_file &file, const std::string &object_name) const -> api_error { const std::string &object_name) const
-> api_error {
api_meta_map meta{}; api_meta_map meta{};
auto res = get_item_meta(file.api_path, meta); auto res{get_item_meta(file.api_path, meta)};
if (res == api_error::item_not_found) { if (res == api_error::item_not_found) {
res = create_directory_paths(file.api_parent, res = create_directory_paths(file.api_parent,
utils::path::get_parent_api_path(object_name)); utils::path::get_parent_api_path(object_name));
@@ -75,14 +76,15 @@ auto s3_provider::add_if_not_found(
auto s3_provider::convert_api_date(std::string_view date) -> std::uint64_t { auto s3_provider::convert_api_date(std::string_view date) -> std::uint64_t {
// 2009-10-12T17:50:30.000Z // 2009-10-12T17:50:30.000Z
auto date_parts = utils::string::split(date, '.', true); auto date_parts{utils::string::split(date, '.', true)};
auto date_time = date_parts.at(0U); auto date_time{date_parts.at(0U)};
auto nanos = auto nanos{
(date_parts.size() <= 1U) (date_parts.size() <= 1U)
? 0U ? 0U
: utils::string::to_uint64( : utils::string::to_uint64(
utils::string::split(date_parts.at(1U), 'Z', true).at(0U)) * utils::string::split(date_parts.at(1U), 'Z', true).at(0U)) *
1000000UL; 1000000UL,
};
struct tm tm1{}; struct tm tm1{};
#if defined(_WIN32) #if defined(_WIN32)
@@ -95,36 +97,12 @@ auto s3_provider::convert_api_date(std::string_view date) -> std::uint64_t {
#endif // defined(_WIN32) #endif // defined(_WIN32)
} }
auto s3_provider::create_directory_impl(const std::string &api_path, auto s3_provider::create_directory_object(const std::string &api_path,
api_meta_map &meta) -> api_error { const std::string &object_name) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
const auto &cfg = get_s3_config(); const auto &cfg{get_s3_config()};
auto is_encrypted = not cfg.encryption_token.empty();
stop_type stop_requested{false};
if (is_encrypted) {
std::string encrypted_file_path;
auto res = get_item_meta(utils::path::get_parent_api_path(api_path),
META_KEY, encrypted_file_path);
if (res != api_error::success) {
utils::error::raise_api_path_error(function_name, api_path, res,
"failed to create file");
return res;
}
data_buffer result;
utils::encryption::encrypt_data(
cfg.encryption_token,
*(utils::string::split(api_path, '/', false).end() - 1U), result);
meta[META_KEY] = utils::path::create_api_path(
utils::path::combine(utils::path::create_api_path(encrypted_file_path),
{utils::collection::to_hex_string(result)}));
}
auto object_name =
utils::path::create_api_path(is_encrypted ? meta[META_KEY] : api_path);
std::string response_data; std::string response_data;
curl::requests::http_put_file put_dir{}; curl::requests::http_put_file put_dir{};
@@ -136,11 +114,12 @@ auto s3_provider::create_directory_impl(const std::string &api_path,
response_data = std::string(data.begin(), data.end()); response_data = std::string(data.begin(), data.end());
}; };
auto res = set_request_path(put_dir, object_name + '/'); auto res{set_request_path(put_dir, object_name + '/')};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
stop_type stop_requested{false};
long response_code{}; long response_code{};
if (not get_comm().make_request(put_dir, response_code, stop_requested)) { if (not get_comm().make_request(put_dir, response_code, stop_requested)) {
utils::error::raise_api_path_error(function_name, api_path, utils::error::raise_api_path_error(function_name, api_path,
@@ -159,20 +138,38 @@ auto s3_provider::create_directory_impl(const std::string &api_path,
return api_error::success; return api_error::success;
} }
auto s3_provider::create_directory_paths( auto s3_provider::create_directory_impl(const std::string &api_path,
const std::string &api_path, const std::string &key) const -> api_error { api_meta_map &meta) -> api_error {
REPERTORY_USES_FUNCTION_NAME();
auto res{set_meta_key(api_path, meta)};
if (res != api_error::success) {
return res;
}
const auto &cfg{get_s3_config()};
auto is_encrypted{not cfg.encryption_token.empty()};
return create_directory_object(
api_path,
utils::path::create_api_path(is_encrypted ? meta[META_KEY] : api_path));
}
auto s3_provider::create_directory_paths(const std::string &api_path,
const std::string &key) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
if (api_path == "/") { if (api_path == "/") {
return api_error::success; return api_error::success;
} }
const auto &cfg = get_s3_config(); const auto &cfg{get_s3_config()};
auto encryption_token = cfg.encryption_token; auto encryption_token{cfg.encryption_token};
auto is_encrypted = not encryption_token.empty(); auto is_encrypted{not encryption_token.empty()};
auto path_parts = utils::string::split(api_path, '/', false); auto path_parts{utils::string::split(api_path, '/', false)};
auto key_parts = utils::string::split(key, '/', false); auto key_parts{utils::string::split(key, '/', false)};
if (is_encrypted && key_parts.size() != path_parts.size()) { if (is_encrypted && key_parts.size() != path_parts.size()) {
return api_error::error; return api_error::error;
@@ -189,7 +186,7 @@ auto s3_provider::create_directory_paths(
utils::path::combine(cur_path, {path_parts.at(idx)})); utils::path::combine(cur_path, {path_parts.at(idx)}));
std::string value; std::string value;
auto res = get_item_meta(cur_path, META_DIRECTORY, value); auto res{get_item_meta(cur_path, META_DIRECTORY, value)};
if (res == api_error::success) { if (res == api_error::success) {
if (not utils::string::to_bool(value)) { if (not utils::string::to_bool(value)) {
return api_error::item_exists; return api_error::item_exists;
@@ -205,42 +202,18 @@ auto s3_provider::create_directory_paths(
} }
if (not exists) { if (not exists) {
std::string response_data; res = create_directory_object(api_path,
curl::requests::http_put_file put_dir{}; (is_encrypted ? cur_key : cur_path));
put_dir.allow_timeout = true;
put_dir.aws_service = "aws:amz:" + cfg.region + ":s3";
put_dir.response_handler = [&response_data](auto &&data,
long /*response_code*/) {
response_data = std::string(data.begin(), data.end());
};
res = set_request_path(put_dir,
(is_encrypted ? cur_key : cur_path) + '/');
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
stop_type stop_requested{false};
long response_code{};
if (not get_comm().make_request(put_dir, response_code,
stop_requested)) {
utils::error::raise_api_path_error(
function_name, cur_path, api_error::comm_error,
"failed to create directory object");
return api_error::comm_error;
} }
if (response_code != http_error_codes::ok) { auto dir{
utils::error::raise_api_path_error( create_api_file(cur_path, cur_key, 0U,
function_name, api_path, response_code, exists ? get_last_modified(true, cur_path)
fmt::format("failed to create directory|response|{}", : utils::time::get_time_now()),
response_data)); };
return api_error::comm_error;
}
}
auto dir = create_api_file(cur_path, cur_key, 0U,
get_last_modified(true, cur_path));
get_api_item_added()(true, dir); get_api_item_added()(true, dir);
} }
@@ -254,30 +227,7 @@ auto s3_provider::create_directory_paths(
auto s3_provider::create_file_extra(const std::string &api_path, auto s3_provider::create_file_extra(const std::string &api_path,
api_meta_map &meta) -> api_error { api_meta_map &meta) -> api_error {
REPERTORY_USES_FUNCTION_NAME(); return set_meta_key(api_path, meta);
const auto &cfg = get_s3_config();
if (not cfg.encryption_token.empty()) {
std::string encrypted_file_path;
auto res = get_item_meta(utils::path::get_parent_api_path(api_path),
META_KEY, encrypted_file_path);
if (res != api_error::success) {
utils::error::raise_api_path_error(function_name, api_path, res,
"failed to create file");
return res;
}
data_buffer result;
utils::encryption::encrypt_data(
cfg.encryption_token,
*(utils::string::split(api_path, '/', false).end() - 1U), result);
meta[META_KEY] = utils::path::create_api_path(
utils::path::combine(utils::path::create_api_path(encrypted_file_path),
{utils::collection::to_hex_string(result)}));
}
return api_error::success;
} }
auto s3_provider::decrypt_object_name(std::string &object_name) const auto s3_provider::decrypt_object_name(std::string &object_name) const
@@ -295,24 +245,26 @@ auto s3_provider::get_directory_item_count(const std::string &api_path) const
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
try { try {
const auto &cfg = get_s3_config(); const auto &cfg{get_s3_config()};
auto is_encrypted = not cfg.encryption_token.empty(); auto is_encrypted{not cfg.encryption_token.empty()};
std::string key; std::string key;
if (is_encrypted) { if (is_encrypted) {
auto res = get_item_meta(api_path, META_KEY, key); auto res{get_item_meta(api_path, META_KEY, key)};
if (res != api_error::success) { if (res != api_error::success) {
return 0U; return 0U;
} }
} }
auto object_name = auto object_name{
api_path == "/" api_path == "/"
? "" ? ""
: utils::path::create_api_path(is_encrypted ? key : api_path); : utils::path::create_api_path(is_encrypted ? key : api_path),
};
std::string response_data{}; std::string response_data{};
long response_code{}; long response_code{};
auto prefix = object_name.empty() ? object_name : object_name + "/"; auto prefix{object_name.empty() ? object_name : object_name + "/"};
auto grab_more{true}; auto grab_more{true};
std::string token{}; std::string token{};
@@ -332,7 +284,7 @@ auto s3_provider::get_directory_item_count(const std::string &api_path) const
} }
pugi::xml_document doc; pugi::xml_document doc;
auto res = doc.load_string(response_data.c_str()); auto res{doc.load_string(response_data.c_str())};
if (res.status != pugi::xml_parse_status::status_ok) { if (res.status != pugi::xml_parse_status::status_ok) {
return total_count; return total_count;
} }
@@ -348,8 +300,9 @@ auto s3_provider::get_directory_item_count(const std::string &api_path) const
.as_string(); .as_string();
} }
auto node_list = auto node_list{
doc.select_nodes("/ListBucketResult/CommonPrefixes/Prefix"); doc.select_nodes("/ListBucketResult/CommonPrefixes/Prefix"),
};
total_count += node_list.size(); total_count += node_list.size();
node_list = doc.select_nodes("/ListBucketResult/Contents"); node_list = doc.select_nodes("/ListBucketResult/Contents");
@@ -367,8 +320,9 @@ auto s3_provider::get_directory_item_count(const std::string &api_path) const
return 0U; return 0U;
} }
auto s3_provider::get_directory_items_impl( auto s3_provider::get_directory_items_impl(const std::string &api_path,
const std::string &api_path, directory_item_list &list) const -> api_error { directory_item_list &list) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
const auto &cfg{get_s3_config()}; const auto &cfg{get_s3_config()};
@@ -402,7 +356,7 @@ auto s3_provider::get_directory_items_impl(
api_error::success) { api_error::success) {
dir_item.size = utils::string::to_uint64(size_str); dir_item.size = utils::string::to_uint64(size_str);
} else { } else {
auto size = node.select_node("Size").node().text().as_ullong(); auto size{node.select_node("Size").node().text().as_ullong()};
dir_item.size = is_encrypted ? utils::encryption::encrypting_reader:: dir_item.size = is_encrypted ? utils::encryption::encrypting_reader::
calculate_decrypted_size(size) calculate_decrypted_size(size)
@@ -411,8 +365,10 @@ auto s3_provider::get_directory_items_impl(
res = get_item_meta(dir_item.api_path, dir_item.meta); res = get_item_meta(dir_item.api_path, dir_item.meta);
if (res == api_error::item_not_found) { if (res == api_error::item_not_found) {
auto last_modified = convert_api_date( auto last_modified{
node.select_node("LastModified").node().text().as_string()); convert_api_date(
node.select_node("LastModified").node().text().as_string()),
};
api_file file{}; api_file file{};
file.api_path = dir_item.api_path; file.api_path = dir_item.api_path;
@@ -438,7 +394,7 @@ auto s3_provider::get_directory_items_impl(
std::string key; std::string key;
if (is_encrypted) { if (is_encrypted) {
auto res = get_item_meta(api_path, META_KEY, key); auto res{get_item_meta(api_path, META_KEY, key)};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
@@ -474,7 +430,7 @@ auto s3_provider::get_directory_items_impl(
} }
pugi::xml_document doc; pugi::xml_document doc;
auto parse_res = doc.load_string(response_data.c_str()); auto parse_res{doc.load_string(response_data.c_str())};
if (parse_res.status != pugi::xml_parse_status::status_ok) { if (parse_res.status != pugi::xml_parse_status::status_ok) {
return api_error::error; return api_error::error;
} }
@@ -490,12 +446,15 @@ auto s3_provider::get_directory_items_impl(
.as_string(); .as_string();
} }
auto node_list = auto node_list{
doc.select_nodes("/ListBucketResult/CommonPrefixes/Prefix"); doc.select_nodes("/ListBucketResult/CommonPrefixes/Prefix"),
};
for (const auto &node : node_list) { for (const auto &node : node_list) {
auto child_object_name = utils::path::create_api_path( auto child_object_name{
utils::path::combine("/", {node.node().text().as_string()})); utils::path::create_api_path(
auto res = add_diretory_item(child_object_name, true, node.node()); utils::path::combine("/", {node.node().text().as_string()})),
};
auto res{add_diretory_item(child_object_name, true, node.node())};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
@@ -503,13 +462,15 @@ auto s3_provider::get_directory_items_impl(
node_list = doc.select_nodes("/ListBucketResult/Contents"); node_list = doc.select_nodes("/ListBucketResult/Contents");
for (const auto &node : node_list) { for (const auto &node : node_list) {
auto child_object_name = utils::path::create_api_path( auto child_object_name{
node.node().select_node("Key").node().text().as_string()); utils::path::create_api_path(
node.node().select_node("Key").node().text().as_string()),
};
if (child_object_name == utils::path::create_api_path(prefix)) { if (child_object_name == utils::path::create_api_path(prefix)) {
continue; continue;
} }
auto res = add_diretory_item(child_object_name, false, node.node()); auto res{add_diretory_item(child_object_name, false, node.node())};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
@@ -519,16 +480,17 @@ auto s3_provider::get_directory_items_impl(
return api_error::success; return api_error::success;
} }
auto s3_provider::get_file(const std::string &api_path, auto s3_provider::get_file(const std::string &api_path, api_file &file) const
api_file &file) const -> api_error { -> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
try { try {
bool is_encrypted{}; bool is_encrypted{};
std::string object_name; std::string object_name;
head_object_result result{}; head_object_result result{};
auto res = auto res{
get_object_info(false, api_path, is_encrypted, object_name, result); get_object_info(false, api_path, is_encrypted, object_name, result),
};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
@@ -559,8 +521,8 @@ auto s3_provider::get_file(const std::string &api_path,
return api_error::error; return api_error::error;
} }
auto s3_provider::get_file_list(api_file_list &list, auto s3_provider::get_file_list(api_file_list &list, std::string &marker) const
std::string &marker) const -> api_error { -> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
try { try {
@@ -578,17 +540,19 @@ auto s3_provider::get_file_list(api_file_list &list,
} }
pugi::xml_document doc; pugi::xml_document doc;
auto result = doc.load_string(response_data.c_str()); auto result{doc.load_string(response_data.c_str())};
if (result.status != pugi::xml_parse_status::status_ok) { if (result.status != pugi::xml_parse_status::status_ok) {
utils::error::raise_error(function_name, result.status, utils::error::raise_error(function_name, result.status,
"failed to parse xml document"); "failed to parse xml document");
return api_error::comm_error; return api_error::comm_error;
} }
auto grab_more = doc.select_node("/ListBucketResult/IsTruncated") auto grab_more{
doc.select_node("/ListBucketResult/IsTruncated")
.node() .node()
.text() .text()
.as_bool(); .as_bool(),
};
if (grab_more) { if (grab_more) {
marker = doc.select_node("/ListBucketResult/NextContinuationToken") marker = doc.select_node("/ListBucketResult/NextContinuationToken")
.node() .node()
@@ -596,24 +560,26 @@ auto s3_provider::get_file_list(api_file_list &list,
.as_string(); .as_string();
} }
auto node_list = doc.select_nodes("/ListBucketResult/Contents"); auto node_list{doc.select_nodes("/ListBucketResult/Contents")};
for (const auto &node : node_list) { for (const auto &node : node_list) {
auto object_name = auto object_name{
std::string{node.node().select_node("Key").node().text().as_string()}; std::string(node.node().select_node("Key").node().text().as_string()),
};
if (utils::string::ends_with(object_name, "/")) { if (utils::string::ends_with(object_name, "/")) {
continue; continue;
} }
auto api_path{object_name}; auto api_path{object_name};
auto is_encrypted = not get_s3_config().encryption_token.empty(); auto is_encrypted{not get_s3_config().encryption_token.empty()};
if (is_encrypted) { if (is_encrypted) {
auto res = decrypt_object_name(api_path); auto res{decrypt_object_name(api_path)};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
} }
auto size = node.node().select_node("Size").node().text().as_ullong(); auto size{node.node().select_node("Size").node().text().as_ullong()};
api_file file{}; api_file file{};
file.api_path = utils::path::create_api_path(api_path); file.api_path = utils::path::create_api_path(api_path);
@@ -630,7 +596,7 @@ auto s3_provider::get_file_list(api_file_list &list,
size) size)
: size; : size;
file.key = is_encrypted ? utils::path::create_api_path(object_name) : ""; file.key = is_encrypted ? utils::path::create_api_path(object_name) : "";
auto res = add_if_not_found(file, file.key); auto res{add_if_not_found(file, file.key)};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
@@ -646,8 +612,9 @@ auto s3_provider::get_file_list(api_file_list &list,
return api_error::error; return api_error::error;
} }
auto s3_provider::get_last_modified( auto s3_provider::get_last_modified(bool directory,
bool directory, const std::string &api_path) const -> std::uint64_t { const std::string &api_path) const
-> std::uint64_t {
bool is_encrypted{}; bool is_encrypted{};
std::string object_name; std::string object_name;
head_object_result result{}; head_object_result result{};
@@ -657,18 +624,19 @@ auto s3_provider::get_last_modified(
: utils::time::get_time_now(); : utils::time::get_time_now();
} }
auto s3_provider::get_object_info( auto s3_provider::get_object_info(bool directory, const std::string &api_path,
bool directory, const std::string &api_path, bool &is_encrypted, bool &is_encrypted, std::string &object_name,
std::string &object_name, head_object_result &result) const -> api_error { head_object_result &result) const
-> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
try { try {
const auto &cfg = get_s3_config(); const auto &cfg{get_s3_config()};
is_encrypted = not cfg.encryption_token.empty(); is_encrypted = not cfg.encryption_token.empty();
std::string key; std::string key;
if (is_encrypted) { if (is_encrypted) {
auto res = get_item_meta(api_path, META_KEY, key); auto res{get_item_meta(api_path, META_KEY, key)};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
@@ -685,8 +653,9 @@ auto s3_provider::get_object_info(
long /*response_code*/) { long /*response_code*/) {
response_data = std::string(data.begin(), data.end()); response_data = std::string(data.begin(), data.end());
}; };
auto res = auto res{
set_request_path(head, directory ? object_name + '/' : object_name); set_request_path(head, directory ? object_name + '/' : object_name),
};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
@@ -718,10 +687,12 @@ auto s3_provider::get_object_info(
return api_error::error; return api_error::error;
} }
auto s3_provider::get_object_list( auto s3_provider::get_object_list(std::string &response_data,
std::string &response_data, long &response_code, long &response_code,
std::optional<std::string> delimiter, std::optional<std::string> prefix, std::optional<std::string> delimiter,
std::optional<std::string> token) const -> bool { std::optional<std::string> prefix,
std::optional<std::string> token) const
-> bool {
curl::requests::http_get get{}; curl::requests::http_get get{};
get.allow_timeout = true; get.allow_timeout = true;
get.aws_service = "aws:amz:" + get_s3_config().region + ":s3"; get.aws_service = "aws:amz:" + get_s3_config().region + ":s3";
@@ -749,8 +720,8 @@ auto s3_provider::get_total_drive_space() const -> std::uint64_t {
return std::numeric_limits<std::int64_t>::max() / std::int64_t(2); return std::numeric_limits<std::int64_t>::max() / std::int64_t(2);
} }
auto s3_provider::is_directory(const std::string &api_path, auto s3_provider::is_directory(const std::string &api_path, bool &exists) const
bool &exists) const -> api_error { -> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
try { try {
@@ -763,8 +734,9 @@ auto s3_provider::is_directory(const std::string &api_path,
bool is_encrypted{}; bool is_encrypted{};
std::string object_name; std::string object_name;
head_object_result result{}; head_object_result result{};
auto res = auto res{
get_object_info(true, api_path, is_encrypted, object_name, result); get_object_info(true, api_path, is_encrypted, object_name, result),
};
if (res != api_error::item_not_found && res != api_error::success) { if (res != api_error::item_not_found && res != api_error::success) {
return res; return res;
} }
@@ -777,8 +749,8 @@ auto s3_provider::is_directory(const std::string &api_path,
return api_error::error; return api_error::error;
} }
auto s3_provider::is_file(const std::string &api_path, auto s3_provider::is_file(const std::string &api_path, bool &exists) const
bool &exists) const -> api_error { -> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
try { try {
@@ -790,8 +762,9 @@ auto s3_provider::is_file(const std::string &api_path,
bool is_encrypted{}; bool is_encrypted{};
std::string object_name; std::string object_name;
head_object_result result{}; head_object_result result{};
auto res = auto res{
get_object_info(false, api_path, is_encrypted, object_name, result); get_object_info(false, api_path, is_encrypted, object_name, result),
};
if (res != api_error::item_not_found && res != api_error::success) { if (res != api_error::item_not_found && res != api_error::success) {
return res; return res;
} }
@@ -815,24 +788,26 @@ auto s3_provider::read_file_bytes(const std::string &api_path, std::size_t size,
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
try { try {
const auto &cfg = get_s3_config(); const auto &cfg{get_s3_config()};
auto is_encrypted = not cfg.encryption_token.empty(); auto is_encrypted{not cfg.encryption_token.empty()};
std::string key; std::string key;
if (is_encrypted) { if (is_encrypted) {
auto res = get_item_meta(api_path, META_KEY, key); auto res{get_item_meta(api_path, META_KEY, key)};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
} }
auto object_name = auto object_name{
utils::path::create_api_path(is_encrypted ? key : api_path); utils::path::create_api_path(is_encrypted ? key : api_path),
};
const auto read_bytes = const auto read_bytes =
[this, &api_path, &cfg, &object_name, [this, &api_path, &cfg, &object_name,
&stop_requested](std::size_t read_size, std::size_t read_offset, &stop_requested](std::size_t read_size, std::size_t read_offset,
data_buffer &read_buffer) -> api_error { data_buffer &read_buffer) -> api_error {
auto res = api_error::error; auto res{api_error::error};
for (std::uint32_t idx = 0U; for (std::uint32_t idx = 0U;
not stop_requested && res != api_error::success && not stop_requested && res != api_error::success &&
idx < get_config().get_retry_read_count() + 1U; idx < get_config().get_retry_read_count() + 1U;
@@ -893,12 +868,12 @@ auto s3_provider::read_file_bytes(const std::string &api_path, std::size_t size,
} }
std::string temp; std::string temp;
auto res = get_item_meta(api_path, META_SIZE, temp); auto res{get_item_meta(api_path, META_SIZE, temp)};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
auto total_size = utils::string::to_uint64(temp); auto total_size{utils::string::to_uint64(temp)};
return utils::encryption::read_encrypted_range( return utils::encryption::read_encrypted_range(
{offset, offset + size - 1U}, {offset, offset + size - 1U},
utils::encryption::generate_key<utils::encryption::hash_256_t>( utils::encryption::generate_key<utils::encryption::hash_256_t>(
@@ -924,19 +899,20 @@ auto s3_provider::remove_directory_impl(const std::string &api_path)
-> api_error { -> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
const auto &cfg = get_s3_config(); const auto &cfg{get_s3_config()};
auto is_encrypted = not cfg.encryption_token.empty(); auto is_encrypted{not cfg.encryption_token.empty()};
std::string key; std::string key;
if (is_encrypted) { if (is_encrypted) {
auto res = get_item_meta(api_path, META_KEY, key); auto res{get_item_meta(api_path, META_KEY, key)};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
} }
auto object_name = auto object_name{
utils::path::create_api_path(is_encrypted ? key : api_path); utils::path::create_api_path(is_encrypted ? key : api_path),
};
std::string response_data; std::string response_data;
curl::requests::http_delete del_dir{}; curl::requests::http_delete del_dir{};
@@ -947,7 +923,7 @@ auto s3_provider::remove_directory_impl(const std::string &api_path)
response_data = std::string(data.begin(), data.end()); response_data = std::string(data.begin(), data.end());
}; };
auto res = set_request_path(del_dir, object_name + '/'); auto res{set_request_path(del_dir, object_name + '/')};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
@@ -976,19 +952,20 @@ auto s3_provider::remove_directory_impl(const std::string &api_path)
auto s3_provider::remove_file_impl(const std::string &api_path) -> api_error { auto s3_provider::remove_file_impl(const std::string &api_path) -> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
const auto &cfg = get_s3_config(); const auto &cfg{get_s3_config()};
auto is_encrypted = not cfg.encryption_token.empty(); auto is_encrypted{not cfg.encryption_token.empty()};
std::string key; std::string key;
if (is_encrypted) { if (is_encrypted) {
auto res = get_item_meta(api_path, META_KEY, key); auto res{get_item_meta(api_path, META_KEY, key)};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
} }
auto object_name = auto object_name{
utils::path::create_api_path(is_encrypted ? key : api_path); utils::path::create_api_path(is_encrypted ? key : api_path),
};
std::string response_data; std::string response_data;
curl::requests::http_delete del_file{}; curl::requests::http_delete del_file{};
@@ -998,7 +975,7 @@ auto s3_provider::remove_file_impl(const std::string &api_path) -> api_error {
long /*response_code*/) { long /*response_code*/) {
response_data = std::string(data.begin(), data.end()); response_data = std::string(data.begin(), data.end());
}; };
auto res = set_request_path(del_file, object_name); auto res{set_request_path(del_file, object_name)};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
@@ -1030,6 +1007,40 @@ auto s3_provider::rename_file(const std::string & /* from_api_path */,
return api_error::not_implemented; return api_error::not_implemented;
} }
auto s3_provider::set_meta_key(const std::string &api_path, api_meta_map &meta)
-> api_error {
REPERTORY_USES_FUNCTION_NAME();
const auto &cfg{get_s3_config()};
auto is_encrypted{not cfg.encryption_token.empty()};
if (not is_encrypted) {
return api_error::success;
}
std::string encrypted_parent_path;
auto res{
get_item_meta(utils::path::get_parent_api_path(api_path), META_KEY,
encrypted_parent_path),
};
if (res != api_error::success) {
utils::error::raise_api_path_error(function_name, api_path, res,
"failed to create file");
return res;
}
data_buffer result;
utils::encryption::encrypt_data(
cfg.encryption_token,
*(utils::string::split(api_path, '/', false).end() - 1U), result);
meta[META_KEY] = utils::path::create_api_path(
utils::path::combine(utils::path::create_api_path(encrypted_parent_path),
{
utils::collection::to_hex_string(result),
}));
return api_error::success;
}
auto s3_provider::start(api_item_added_callback api_item_added, auto s3_provider::start(api_item_added_callback api_item_added,
i_file_manager *mgr) -> bool { i_file_manager *mgr) -> bool {
event_system::instance().raise<service_started>("s3_provider"); event_system::instance().raise<service_started>("s3_provider");
@@ -1051,26 +1062,27 @@ auto s3_provider::upload_file_impl(const std::string &api_path,
std::uint64_t file_size{}; std::uint64_t file_size{};
if (utils::file::file{source_path}.exists()) { if (utils::file::file{source_path}.exists()) {
auto opt_size = utils::file::file{source_path}.size(); auto opt_size{utils::file::file{source_path}.size()};
if (not opt_size.has_value()) { if (not opt_size.has_value()) {
return api_error::comm_error; return api_error::comm_error;
} }
file_size = opt_size.value(); file_size = opt_size.value();
} }
const auto &cfg = get_s3_config(); const auto &cfg{get_s3_config()};
auto is_encrypted = not cfg.encryption_token.empty(); auto is_encrypted{not cfg.encryption_token.empty()};
std::string key; std::string key;
if (is_encrypted) { if (is_encrypted) {
auto res = get_item_meta(api_path, META_KEY, key); auto res{get_item_meta(api_path, META_KEY, key)};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
} }
auto object_name = auto object_name{
utils::path::create_api_path(is_encrypted ? key : api_path); utils::path::create_api_path(is_encrypted ? key : api_path),
};
std::string response_data; std::string response_data;
curl::requests::http_put_file put_file{}; curl::requests::http_put_file put_file{};
@@ -1081,7 +1093,7 @@ auto s3_provider::upload_file_impl(const std::string &api_path,
}; };
put_file.source_path = source_path; put_file.source_path = source_path;
auto res = set_request_path(put_file, object_name); auto res{set_request_path(put_file, object_name)};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }

View File

@@ -111,8 +111,8 @@ auto sia_provider::get_directory_item_count(const std::string &api_path) const
if (object_list.contains("entries")) { if (object_list.contains("entries")) {
for (const auto &entry : object_list.at("entries")) { for (const auto &entry : object_list.at("entries")) {
try { try {
auto name = entry.at("name").get<std::string>(); auto name{entry.at("name").get<std::string>()};
auto entry_api_path = utils::path::create_api_path(name); auto entry_api_path{utils::path::create_api_path(name)};
if (utils::string::ends_with(name, "/") && if (utils::string::ends_with(name, "/") &&
(entry_api_path == api_path)) { (entry_api_path == api_path)) {
continue; continue;
@@ -148,10 +148,10 @@ auto sia_provider::get_directory_items_impl(const std::string &api_path,
if (object_list.contains("entries")) { if (object_list.contains("entries")) {
for (const auto &entry : object_list.at("entries")) { for (const auto &entry : object_list.at("entries")) {
try { try {
auto name = entry.at("name").get<std::string>(); auto name{entry.at("name").get<std::string>()};
auto entry_api_path = utils::path::create_api_path(name); auto entry_api_path{utils::path::create_api_path(name)};
auto directory = utils::string::ends_with(name, "/"); auto directory{utils::string::ends_with(name, "/")};
if (directory && (entry_api_path == api_path)) { if (directory && (entry_api_path == api_path)) {
continue; continue;
} }
@@ -164,7 +164,7 @@ auto sia_provider::get_directory_items_impl(const std::string &api_path,
: entry["size"].get<std::uint64_t>(), : entry["size"].get<std::uint64_t>(),
get_last_modified(entry)); get_last_modified(entry));
get_api_item_added()(directory, file); get_api_item_added()(directory, file);
auto res = get_item_meta(entry_api_path, meta); auto res{get_item_meta(entry_api_path, meta)};
if (res != api_error::success) { if (res != api_error::success) {
utils::error::raise_api_path_error(function_name, entry_api_path, utils::error::raise_api_path_error(function_name, entry_api_path,
res, "failed to get item meta"); res, "failed to get item meta");
@@ -201,18 +201,19 @@ auto sia_provider::get_file(const std::string &api_path, api_file &file) const
try { try {
json file_data{}; json file_data{};
auto res = get_object_info(api_path, file_data); auto res{get_object_info(api_path, file_data)};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
auto slabs = file_data["object"]["Slabs"]; auto slabs{file_data["object"]["Slabs"]};
auto size = std::accumulate( auto size{
std::accumulate(
slabs.begin(), slabs.end(), std::uint64_t(0U), slabs.begin(), slabs.end(), std::uint64_t(0U),
[](std::uint64_t total_size, [](auto &&total_size, const json &slab) -> std::uint64_t {
const nlohmann::json &slab) -> std::uint64_t {
return total_size + slab["Length"].get<std::uint64_t>(); return total_size + slab["Length"].get<std::uint64_t>();
}); }),
};
api_meta_map meta{}; api_meta_map meta{};
if (get_item_meta(api_path, meta) == api_error::item_not_found) { if (get_item_meta(api_path, meta) == api_error::item_not_found) {
@@ -247,8 +248,8 @@ auto sia_provider::get_file_list(api_file_list &list,
if (object_list.contains("entries")) { if (object_list.contains("entries")) {
for (const auto &entry : object_list.at("entries")) { for (const auto &entry : object_list.at("entries")) {
auto name = entry.at("name").get<std::string>(); auto name{entry.at("name").get<std::string>()};
auto entry_api_path = utils::path::create_api_path(name); auto entry_api_path{utils::path::create_api_path(name)};
if (utils::string::ends_with(name, "/")) { if (utils::string::ends_with(name, "/")) {
if (entry_api_path == utils::path::create_api_path(api_path)) { if (entry_api_path == utils::path::create_api_path(api_path)) {
@@ -258,12 +259,14 @@ auto sia_provider::get_file_list(api_file_list &list,
api_meta_map meta{}; api_meta_map meta{};
if (get_item_meta(entry_api_path, meta) == if (get_item_meta(entry_api_path, meta) ==
api_error::item_not_found) { api_error::item_not_found) {
auto dir = create_api_file(entry_api_path, "", 0U, auto dir{
get_last_modified(entry)); create_api_file(entry_api_path, "", 0U,
get_last_modified(entry)),
};
get_api_item_added()(true, dir); get_api_item_added()(true, dir);
} }
auto res = get_files_in_dir(entry_api_path); auto res{get_files_in_dir(entry_api_path)};
if (res != api_error::success) { if (res != api_error::success) {
return res; return res;
} }
@@ -480,7 +483,7 @@ auto sia_provider::is_file(const std::string &api_path, bool &exists) const
} }
json file_data{}; json file_data{};
auto res = get_object_info(api_path, file_data); auto res{get_object_info(api_path, file_data)};
if (res == api_error::item_not_found) { if (res == api_error::item_not_found) {
return api_error::success; return api_error::success;
} }

View File

@@ -35,7 +35,7 @@ void polling::frequency_thread(
unique_mutex_lock lock(mutex_); unique_mutex_lock lock(mutex_);
auto futures = std::accumulate( auto futures = std::accumulate(
items_.begin(), items_.end(), std::deque<tasks::task_ptr>{}, items_.begin(), items_.end(), std::deque<tasks::task_ptr>{},
[this, &freq](auto &&list, auto &&item) { [this, &freq](auto &&list, auto &&item) -> auto {
if (item.second.freq != freq) { if (item.second.freq != freq) {
return list; return list;
} }

View File

@@ -30,12 +30,16 @@ TYPED_TEST(file_db_test, can_add_and_remove_directory) {
EXPECT_EQ(api_error::success, this->file_db->add_directory("/", "c:\\test")); EXPECT_EQ(api_error::success, this->file_db->add_directory("/", "c:\\test"));
auto list = this->file_db->get_item_list(); stop_type stop_requested{false};
auto list = this->file_db->get_item_list(stop_requested);
EXPECT_EQ(1U, list.size()); EXPECT_EQ(1U, list.size());
EXPECT_STREQ("/", list.at(0U).api_path.c_str());
EXPECT_TRUE(list.at(0U).directory);
EXPECT_STREQ("c:\\test", list.at(0U).source_path.c_str());
EXPECT_EQ(api_error::success, this->file_db->remove_item("/")); EXPECT_EQ(api_error::success, this->file_db->remove_item("/"));
list = this->file_db->get_item_list(); list = this->file_db->get_item_list(stop_requested);
EXPECT_EQ(0U, list.size()); EXPECT_EQ(0U, list.size());
} }
@@ -49,12 +53,16 @@ TYPED_TEST(file_db_test, can_add_and_remove_file) {
"c:\\test\\file.txt", "c:\\test\\file.txt",
})); }));
auto list = this->file_db->get_item_list(); stop_type stop_requested{false};
auto list = this->file_db->get_item_list(stop_requested);
EXPECT_EQ(1U, list.size()); EXPECT_EQ(1U, list.size());
EXPECT_STREQ("/file", list.at(0U).api_path.c_str());
EXPECT_FALSE(list.at(0U).directory);
EXPECT_STREQ("c:\\test\\file.txt", list.at(0U).source_path.c_str());
EXPECT_EQ(api_error::success, this->file_db->remove_item("/file")); EXPECT_EQ(api_error::success, this->file_db->remove_item("/file"));
list = this->file_db->get_item_list(); list = this->file_db->get_item_list(stop_requested);
EXPECT_EQ(0U, list.size()); EXPECT_EQ(0U, list.size());
} }