refactor file manager db
This commit is contained in:
parent
f276356172
commit
7567e3289c
87
repertory/librepertory/include/db/i_file_mgr_db.hpp
Normal file
87
repertory/librepertory/include/db/i_file_mgr_db.hpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef REPERTORY_INCLUDE_DB_I_FILE_MGR_DB_HPP_
|
||||||
|
#define REPERTORY_INCLUDE_DB_I_FILE_MGR_DB_HPP_
|
||||||
|
|
||||||
|
#include "types/repertory.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
class i_file_mgr_db {
|
||||||
|
INTERFACE_SETUP(i_file_mgr_db);
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct resume_entry final {
|
||||||
|
std::string api_path;
|
||||||
|
std::uint64_t chunk_size{};
|
||||||
|
boost::dynamic_bitset<> read_state;
|
||||||
|
std::string source_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct upload_active_entry final {
|
||||||
|
std::string api_path;
|
||||||
|
std::string source_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct upload_entry final {
|
||||||
|
std::string api_path;
|
||||||
|
std::uint64_t date_time{};
|
||||||
|
std::string source_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
[[nodiscard]] virtual auto add_resume(resume_entry entry) -> bool = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto add_upload(upload_entry entry) -> bool = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto
|
||||||
|
add_upload_active(upload_active_entry entry) -> bool = 0;
|
||||||
|
|
||||||
|
virtual void clear() = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto
|
||||||
|
get_next_upload() const -> std::optional<upload_entry> = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto
|
||||||
|
get_resume_list() const -> std::vector<resume_entry> = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto get_upload(const std::string &api_path) const
|
||||||
|
-> std::optional<upload_entry> = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto
|
||||||
|
get_upload_active_list() const -> std::vector<upload_active_entry> = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto
|
||||||
|
remove_resume(const std::string &api_path) -> bool = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto
|
||||||
|
remove_upload(const std::string &api_path) -> bool = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto
|
||||||
|
remove_upload_active(const std::string &api_path) -> bool = 0;
|
||||||
|
|
||||||
|
[[nodiscard]] virtual auto
|
||||||
|
rename_resume(const std::string &from_api_path,
|
||||||
|
const std::string &to_api_path) -> bool = 0;
|
||||||
|
};
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
|
#endif // REPERTORY_INCLUDE_DB_I_FILE_MGR_DB_HPP_
|
91
repertory/librepertory/include/db/rdb_file_mgr_db.hpp
Normal file
91
repertory/librepertory/include/db/rdb_file_mgr_db.hpp
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef REPERTORY_INCLUDE_DB_RDB_FILE_MGR_DB_HPP_
|
||||||
|
#define REPERTORY_INCLUDE_DB_RDB_FILE_MGR_DB_HPP_
|
||||||
|
|
||||||
|
#include "db/i_file_mgr_db.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
class app_config;
|
||||||
|
|
||||||
|
class rdb_file_mgr_db final : public i_file_mgr_db {
|
||||||
|
public:
|
||||||
|
rdb_file_mgr_db(const app_config &cfg);
|
||||||
|
~rdb_file_mgr_db() override;
|
||||||
|
|
||||||
|
rdb_file_mgr_db(const rdb_file_mgr_db &) = delete;
|
||||||
|
rdb_file_mgr_db(rdb_file_mgr_db &&) = delete;
|
||||||
|
auto operator=(const rdb_file_mgr_db &) -> rdb_file_mgr_db & = delete;
|
||||||
|
auto operator=(rdb_file_mgr_db &&) -> rdb_file_mgr_db & = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const app_config &cfg_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<rocksdb::DB> db_;
|
||||||
|
std::atomic<std::uint64_t> id_{0U};
|
||||||
|
rocksdb::ColumnFamilyHandle *resume_family_{};
|
||||||
|
rocksdb::ColumnFamilyHandle *upload_active_family_{};
|
||||||
|
rocksdb::ColumnFamilyHandle *upload_family_{};
|
||||||
|
|
||||||
|
private:
|
||||||
|
void create_or_open(bool clear);
|
||||||
|
|
||||||
|
public:
|
||||||
|
[[nodiscard]] auto add_resume(resume_entry entry) -> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto add_upload(upload_entry entry) -> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto
|
||||||
|
add_upload_active(upload_active_entry entry) -> bool override;
|
||||||
|
|
||||||
|
void clear() override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto
|
||||||
|
get_next_upload() const -> std::optional<upload_entry> override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto
|
||||||
|
get_resume_list() const -> std::vector<resume_entry> override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_upload(const std::string &api_path) const
|
||||||
|
-> std::optional<upload_entry> override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto
|
||||||
|
get_upload_active_list() const -> std::vector<upload_active_entry> override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto
|
||||||
|
remove_resume(const std::string &api_path) -> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto
|
||||||
|
remove_upload(const std::string &api_path) -> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto
|
||||||
|
remove_upload_active(const std::string &api_path) -> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto
|
||||||
|
rename_resume(const std::string &from_api_path,
|
||||||
|
const std::string &to_api_path) -> bool override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
|
#endif // REPERTORY_INCLUDE_DB_RDB_FILE_MGR_DB_HPP_
|
82
repertory/librepertory/include/db/sqlite_file_mgr_db.hpp
Normal file
82
repertory/librepertory/include/db/sqlite_file_mgr_db.hpp
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef REPERTORY_INCLUDE_DB_SQLITE_FILE_MGR_DB_HPP_
|
||||||
|
#define REPERTORY_INCLUDE_DB_SQLITE_FILE_MGR_DB_HPP_
|
||||||
|
|
||||||
|
#include "db/i_file_mgr_db.hpp"
|
||||||
|
#include "utils/db/sqlite/db_common.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
class app_config;
|
||||||
|
|
||||||
|
class sqlite_file_mgr_db final : public i_file_mgr_db {
|
||||||
|
public:
|
||||||
|
sqlite_file_mgr_db(const app_config &cfg);
|
||||||
|
~sqlite_file_mgr_db() override;
|
||||||
|
|
||||||
|
sqlite_file_mgr_db(const sqlite_file_mgr_db &) = delete;
|
||||||
|
sqlite_file_mgr_db(sqlite_file_mgr_db &&) = delete;
|
||||||
|
auto operator=(const sqlite_file_mgr_db &) -> sqlite_file_mgr_db & = delete;
|
||||||
|
auto operator=(sqlite_file_mgr_db &&) -> sqlite_file_mgr_db & = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
utils::db::sqlite::db3_t db_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
[[nodiscard]] auto add_resume(resume_entry entry) -> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto add_upload(upload_entry entry) -> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto
|
||||||
|
add_upload_active(upload_active_entry entry) -> bool override;
|
||||||
|
|
||||||
|
void clear() override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto
|
||||||
|
get_next_upload() const -> std::optional<upload_entry> override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto
|
||||||
|
get_resume_list() const -> std::vector<resume_entry> override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_upload(const std::string &api_path) const
|
||||||
|
-> std::optional<upload_entry> override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto
|
||||||
|
get_upload_active_list() const -> std::vector<upload_active_entry> override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto
|
||||||
|
remove_resume(const std::string &api_path) -> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto
|
||||||
|
remove_upload(const std::string &api_path) -> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto
|
||||||
|
remove_upload_active(const std::string &api_path) -> bool override;
|
||||||
|
|
||||||
|
[[nodiscard]] auto
|
||||||
|
rename_resume(const std::string &from_api_path,
|
||||||
|
const std::string &to_api_path) -> bool override;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
|
#endif // REPERTORY_INCLUDE_DB_SQLITE_FILE_MGR_DB_HPP_
|
@ -22,15 +22,14 @@
|
|||||||
#ifndef REPERTORY_INCLUDE_FILE_MANAGER_FILE_MANAGER_HPP_
|
#ifndef REPERTORY_INCLUDE_FILE_MANAGER_FILE_MANAGER_HPP_
|
||||||
#define REPERTORY_INCLUDE_FILE_MANAGER_FILE_MANAGER_HPP_
|
#define REPERTORY_INCLUDE_FILE_MANAGER_FILE_MANAGER_HPP_
|
||||||
|
|
||||||
|
#include "db/i_file_mgr_db.hpp"
|
||||||
#include "events/event_system.hpp"
|
#include "events/event_system.hpp"
|
||||||
#include "events/events.hpp"
|
#include "events/events.hpp"
|
||||||
#include "file_manager/i_file_manager.hpp"
|
#include "file_manager/i_file_manager.hpp"
|
||||||
#include "file_manager/i_open_file.hpp"
|
#include "file_manager/i_open_file.hpp"
|
||||||
#include "file_manager/i_upload_manager.hpp"
|
#include "file_manager/i_upload_manager.hpp"
|
||||||
#include "file_manager/upload.hpp"
|
#include "file_manager/upload.hpp"
|
||||||
#include "platform/platform.hpp"
|
|
||||||
#include "types/repertory.hpp"
|
#include "types/repertory.hpp"
|
||||||
#include "utils/db/sqlite/db_common.hpp"
|
|
||||||
#include "utils/file.hpp"
|
#include "utils/file.hpp"
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
@ -57,7 +56,7 @@ private:
|
|||||||
i_provider &provider_;
|
i_provider &provider_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
utils::db::sqlite::db3_t db_;
|
std::unique_ptr<i_file_mgr_db> mgr_db_;
|
||||||
std::atomic<std::uint64_t> next_handle_{0U};
|
std::atomic<std::uint64_t> next_handle_{0U};
|
||||||
mutable std::recursive_mutex open_file_mtx_;
|
mutable std::recursive_mutex open_file_mtx_;
|
||||||
std::unordered_map<std::string, std::shared_ptr<i_closeable_open_file>>
|
std::unordered_map<std::string, std::shared_ptr<i_closeable_open_file>>
|
||||||
@ -132,12 +131,13 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] auto get_open_handle_count() const -> std::size_t;
|
[[nodiscard]] auto get_open_handle_count() const -> std::size_t;
|
||||||
|
|
||||||
[[nodiscard]] auto get_stored_downloads() const -> std::vector<json>;
|
[[nodiscard]] auto
|
||||||
|
get_stored_downloads() const -> std::vector<i_file_mgr_db::resume_entry>;
|
||||||
|
|
||||||
[[nodiscard]] auto has_no_open_file_handles() const -> bool override;
|
[[nodiscard]] auto has_no_open_file_handles() const -> bool override;
|
||||||
|
|
||||||
[[nodiscard]] auto is_processing(const std::string &api_path) const
|
[[nodiscard]] auto
|
||||||
-> bool override;
|
is_processing(const std::string &api_path) const -> bool override;
|
||||||
|
|
||||||
#if defined(PROJECT_TESTING)
|
#if defined(PROJECT_TESTING)
|
||||||
[[nodiscard]] auto open(std::shared_ptr<i_closeable_open_file> of,
|
[[nodiscard]] auto open(std::shared_ptr<i_closeable_open_file> of,
|
||||||
@ -150,13 +150,13 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] auto remove_file(const std::string &api_path) -> api_error;
|
[[nodiscard]] auto remove_file(const std::string &api_path) -> api_error;
|
||||||
|
|
||||||
[[nodiscard]] auto rename_directory(const std::string &from_api_path,
|
[[nodiscard]] auto
|
||||||
const std::string &to_api_path)
|
rename_directory(const std::string &from_api_path,
|
||||||
-> api_error;
|
const std::string &to_api_path) -> api_error;
|
||||||
|
|
||||||
[[nodiscard]] auto rename_file(const std::string &from_api_path,
|
[[nodiscard]] auto rename_file(const std::string &from_api_path,
|
||||||
const std::string &to_api_path, bool overwrite)
|
const std::string &to_api_path,
|
||||||
-> api_error;
|
bool overwrite) -> api_error;
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
|
|
||||||
|
116
repertory/librepertory/src/db/rdb_file_mgr_db.cpp
Normal file
116
repertory/librepertory/src/db/rdb_file_mgr_db.cpp
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "db/rdb_file_mgr_db.hpp"
|
||||||
|
|
||||||
|
#include "app_config.hpp"
|
||||||
|
#include "types/startup_exception.hpp"
|
||||||
|
#include "utils/config.hpp"
|
||||||
|
#include "utils/error_utils.hpp"
|
||||||
|
#include "utils/file.hpp"
|
||||||
|
#include "utils/path.hpp"
|
||||||
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
[[nodiscard]] auto
|
||||||
|
create_rocksdb(const repertory::app_config &cfg, const std::string &name,
|
||||||
|
const std::vector<rocksdb::ColumnFamilyDescriptor> &families,
|
||||||
|
std::vector<rocksdb::ColumnFamilyHandle *> &handles,
|
||||||
|
bool clear) -> std::unique_ptr<rocksdb::DB> {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
auto path = repertory::utils::path::combine(cfg.get_data_directory(), {name});
|
||||||
|
if (clear &&
|
||||||
|
not repertory::utils::file::directory{path}.remove_recursively()) {
|
||||||
|
repertory::utils::error::raise_error(
|
||||||
|
function_name, "failed to remove file mgr db|" + path);
|
||||||
|
}
|
||||||
|
|
||||||
|
rocksdb::Options options{};
|
||||||
|
options.create_if_missing = true;
|
||||||
|
options.create_missing_column_families = true;
|
||||||
|
options.db_log_dir = cfg.get_log_directory();
|
||||||
|
options.keep_log_file_num = 10;
|
||||||
|
|
||||||
|
rocksdb::DB *ptr{};
|
||||||
|
auto status = rocksdb::DB::Open(options, path, families, &handles, &ptr);
|
||||||
|
if (not status.ok()) {
|
||||||
|
repertory::utils::error::raise_error(function_name, status.ToString());
|
||||||
|
throw repertory::startup_exception(status.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::unique_ptr<rocksdb::DB>(ptr);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
rdb_file_mgr_db::rdb_file_mgr_db(const app_config &cfg) : cfg_(cfg) {
|
||||||
|
create_or_open(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
rdb_file_mgr_db::~rdb_file_mgr_db() { db_.reset(); }
|
||||||
|
|
||||||
|
void rdb_file_mgr_db::create_or_open(bool clear) {
|
||||||
|
db_.reset();
|
||||||
|
|
||||||
|
auto families = std::vector<rocksdb::ColumnFamilyDescriptor>();
|
||||||
|
families.emplace_back(rocksdb::kDefaultColumnFamilyName,
|
||||||
|
rocksdb::ColumnFamilyOptions());
|
||||||
|
families.emplace_back("upload_active", rocksdb::ColumnFamilyOptions());
|
||||||
|
families.emplace_back("upload", rocksdb::ColumnFamilyOptions());
|
||||||
|
|
||||||
|
auto handles = std::vector<rocksdb::ColumnFamilyHandle *>();
|
||||||
|
db_ = create_rocksdb(cfg_, "mgr", families, handles, clear);
|
||||||
|
|
||||||
|
std::size_t idx{};
|
||||||
|
resume_family_ = handles[idx++];
|
||||||
|
upload_active_family_ = handles[idx++];
|
||||||
|
upload_family_ = handles[idx++];
|
||||||
|
}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::add_resume(resume_entry entry) -> bool {}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::add_upload(upload_entry entry) -> bool {}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::add_upload_active(upload_active_entry entry) -> bool {}
|
||||||
|
|
||||||
|
void rdb_file_mgr_db::clear() {}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::get_next_upload() const -> std::optional<upload_entry> {}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::get_resume_list() const -> std::vector<resume_entry> {}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::get_upload(const std::string &api_path) const
|
||||||
|
-> std::optional<upload_entry> {}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::get_upload_active_list() const
|
||||||
|
-> std::vector<upload_active_entry> {}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::remove_resume(const std::string &api_path) -> bool {}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::remove_upload(const std::string &api_path) -> bool {}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::remove_upload_active(const std::string &api_path)
|
||||||
|
-> bool {}
|
||||||
|
|
||||||
|
auto rdb_file_mgr_db::rename_resume(const std::string &from_api_path,
|
||||||
|
const std::string &to_api_path) -> bool {}
|
||||||
|
} // namespace repertory
|
274
repertory/librepertory/src/db/sqlite_file_mgr_db.cpp
Normal file
274
repertory/librepertory/src/db/sqlite_file_mgr_db.cpp
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "db/sqlite_file_mgr_db.hpp"
|
||||||
|
|
||||||
|
#include "app_config.hpp"
|
||||||
|
#include "utils/config.hpp"
|
||||||
|
#include "utils/db/sqlite/db_common.hpp"
|
||||||
|
#include "utils/db/sqlite/db_delete.hpp"
|
||||||
|
#include "utils/db/sqlite/db_insert.hpp"
|
||||||
|
#include "utils/db/sqlite/db_select.hpp"
|
||||||
|
#include "utils/db/sqlite/db_update.hpp"
|
||||||
|
#include "utils/error_utils.hpp"
|
||||||
|
#include "utils/path.hpp"
|
||||||
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const std::string resume_table = "resume";
|
||||||
|
const std::string upload_table = "upload";
|
||||||
|
const std::string upload_active_table = "upload_active";
|
||||||
|
const std::map<std::string, std::string> sql_create_tables{
|
||||||
|
{
|
||||||
|
{resume_table},
|
||||||
|
{
|
||||||
|
"CREATE TABLE IF NOT EXISTS " + resume_table +
|
||||||
|
"("
|
||||||
|
"api_path TEXT PRIMARY KEY ASC, "
|
||||||
|
"chunk_size INTEGER, "
|
||||||
|
"read_state TEXT, "
|
||||||
|
"source_path TEXT"
|
||||||
|
");",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{upload_table},
|
||||||
|
{
|
||||||
|
"CREATE TABLE IF NOT EXISTS " + upload_table +
|
||||||
|
"("
|
||||||
|
"id INTEGER PRIMARY KEY AUTOINCREMENT, "
|
||||||
|
"api_path TEXT UNIQUE, "
|
||||||
|
"date_time INTEGER, "
|
||||||
|
"source_path TEXT"
|
||||||
|
");",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{upload_active_table},
|
||||||
|
{
|
||||||
|
"CREATE TABLE IF NOT EXISTS " + upload_active_table +
|
||||||
|
"("
|
||||||
|
"api_path TEXT PRIMARY KEY ASC, "
|
||||||
|
"source_path TEXT"
|
||||||
|
");",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
sqlite_file_mgr_db::sqlite_file_mgr_db(const app_config &cfg) {
|
||||||
|
db_ = utils::db::sqlite::create_db(
|
||||||
|
utils::path::combine(cfg.get_data_directory(), {"mgr.db"}),
|
||||||
|
sql_create_tables);
|
||||||
|
}
|
||||||
|
|
||||||
|
sqlite_file_mgr_db::~sqlite_file_mgr_db() { db_.reset(); }
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::add_resume(resume_entry entry) -> bool {
|
||||||
|
return utils::db::sqlite::db_insert{*db_, resume_table}
|
||||||
|
.or_replace()
|
||||||
|
.column_value("api_path", entry.api_path)
|
||||||
|
.column_value("chunk_size", static_cast<std::int64_t>(entry.chunk_size))
|
||||||
|
.column_value("read_state",
|
||||||
|
utils::string::from_dynamic_bitset(entry.read_state))
|
||||||
|
.column_value("source_path", entry.source_path)
|
||||||
|
.go()
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::add_upload(upload_entry entry) -> bool {
|
||||||
|
return utils::db::sqlite::db_insert{*db_, upload_table}
|
||||||
|
.or_replace()
|
||||||
|
.column_value("api_path", entry.api_path)
|
||||||
|
.column_value("date_time", static_cast<std::int64_t>(entry.date_time))
|
||||||
|
.column_value("source_path", entry.source_path)
|
||||||
|
.go()
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::add_upload_active(upload_active_entry entry) -> bool {
|
||||||
|
return utils::db::sqlite::db_insert{*db_, upload_table}
|
||||||
|
.or_replace()
|
||||||
|
.column_value("api_path", entry.api_path)
|
||||||
|
.column_value("source_path", entry.source_path)
|
||||||
|
.go()
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
void sqlite_file_mgr_db::clear() {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
auto result = utils::db::sqlite::db_delete{*db_, resume_table}.go();
|
||||||
|
if (not result.ok()) {
|
||||||
|
utils::error::raise_error(function_name,
|
||||||
|
"failed to clear resume table|" +
|
||||||
|
std::to_string(result.get_error()));
|
||||||
|
}
|
||||||
|
|
||||||
|
result = utils::db::sqlite::db_delete{*db_, upload_active_table}.go();
|
||||||
|
if (not result.ok()) {
|
||||||
|
utils::error::raise_error(function_name,
|
||||||
|
"failed to clear upload active table|" +
|
||||||
|
std::to_string(result.get_error()));
|
||||||
|
}
|
||||||
|
|
||||||
|
result = utils::db::sqlite::db_delete{*db_, upload_table}.go();
|
||||||
|
if (not result.ok()) {
|
||||||
|
utils::error::raise_error(function_name,
|
||||||
|
"failed to clear upload table|" +
|
||||||
|
std::to_string(result.get_error()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::get_next_upload() const
|
||||||
|
-> std::optional<upload_entry> {
|
||||||
|
auto result = utils::db::sqlite::db_select{*db_, upload_table}
|
||||||
|
.order_by("id", true)
|
||||||
|
.limit(1)
|
||||||
|
.go();
|
||||||
|
std::optional<utils::db::sqlite::db_result::row> row;
|
||||||
|
if (not result.get_row(row) || not row.has_value()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return upload_entry{
|
||||||
|
row->get_column("api_path").get_value<std::string>(),
|
||||||
|
static_cast<std::uint64_t>(
|
||||||
|
row->get_column("date_time").get_value<std::int64_t>()),
|
||||||
|
row->get_column("source_path").get_value<std::string>(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::get_resume_list() const -> std::vector<resume_entry> {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
std::vector<resume_entry> ret;
|
||||||
|
auto result = utils::db::sqlite::db_select{*db_, resume_table}.go();
|
||||||
|
while (result.has_row()) {
|
||||||
|
try {
|
||||||
|
std::optional<utils::db::sqlite::db_result::row> row;
|
||||||
|
if (not result.get_row(row)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (not row.has_value()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.push_back(resume_entry{
|
||||||
|
row->get_column("api_path").get_value<std::string>(),
|
||||||
|
static_cast<std::uint64_t>(
|
||||||
|
row->get_column("chunk_size").get_value<std::int64_t>()),
|
||||||
|
utils::string::to_dynamic_bitset(
|
||||||
|
row->get_column("read_state").get_value<std::string>()),
|
||||||
|
row->get_column("source_path").get_value<std::string>(),
|
||||||
|
});
|
||||||
|
} catch (const std::exception &ex) {
|
||||||
|
utils::error::raise_error(function_name, ex, "query error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::get_upload(const std::string &api_path) const
|
||||||
|
-> std::optional<upload_entry> {
|
||||||
|
auto result = utils::db::sqlite::db_select{*db_, upload_table}
|
||||||
|
.column("source_path")
|
||||||
|
.where("api_path")
|
||||||
|
.equals(api_path)
|
||||||
|
.go();
|
||||||
|
std::optional<utils::db::sqlite::db_result::row> row;
|
||||||
|
if (not result.get_row(row) || not row.has_value()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return upload_entry{
|
||||||
|
row->get_column("api_path").get_value<std::string>(),
|
||||||
|
static_cast<std::uint64_t>(
|
||||||
|
row->get_column("date_time").get_value<std::int64_t>()),
|
||||||
|
row->get_column("source_path").get_value<std::string>(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::get_upload_active_list() const
|
||||||
|
-> std::vector<upload_active_entry> {
|
||||||
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
|
std::vector<upload_active_entry> ret;
|
||||||
|
auto result = utils::db::sqlite::db_select{*db_, upload_active_table}.go();
|
||||||
|
while (result.has_row()) {
|
||||||
|
try {
|
||||||
|
std::optional<utils::db::sqlite::db_result::row> row;
|
||||||
|
if (not result.get_row(row)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (not row.has_value()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.push_back(upload_active_entry{
|
||||||
|
row->get_column("api_path").get_value<std::string>(),
|
||||||
|
row->get_column("source_path").get_value<std::string>(),
|
||||||
|
});
|
||||||
|
} catch (const std::exception &ex) {
|
||||||
|
utils::error::raise_error(function_name, ex, "query error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::remove_resume(const std::string &api_path) -> bool {
|
||||||
|
return utils::db::sqlite::db_delete{*db_, resume_table}
|
||||||
|
.where("api_path")
|
||||||
|
.equals(api_path)
|
||||||
|
.go()
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::remove_upload(const std::string &api_path) -> bool {
|
||||||
|
return utils::db::sqlite::db_delete{*db_, upload_table}
|
||||||
|
.where("api_path")
|
||||||
|
.equals(api_path)
|
||||||
|
.go()
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::remove_upload_active(const std::string &api_path)
|
||||||
|
-> bool {
|
||||||
|
return utils::db::sqlite::db_delete{*db_, upload_active_table}
|
||||||
|
.where("api_path")
|
||||||
|
.equals(api_path)
|
||||||
|
.go()
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sqlite_file_mgr_db::rename_resume(const std::string &from_api_path,
|
||||||
|
const std::string &to_api_path) -> bool {
|
||||||
|
return utils::db::sqlite::db_update{*db_, resume_table}
|
||||||
|
.column_value("api_path", to_api_path)
|
||||||
|
.where("api_path")
|
||||||
|
.equals(from_api_path)
|
||||||
|
.go()
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
} // namespace repertory
|
@ -64,7 +64,8 @@ void sqlite_meta_db::clear() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
utils::error::raise_error(function_name,
|
utils::error::raise_error(function_name,
|
||||||
"failed to clear meta db|" + result.get_error());
|
"failed to clear meta db|" +
|
||||||
|
std::to_string(result.get_error()));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto sqlite_meta_db::get_api_path(const std::string &source_path,
|
auto sqlite_meta_db::get_api_path(const std::string &source_path,
|
||||||
|
@ -22,19 +22,16 @@
|
|||||||
#include "file_manager/file_manager.hpp"
|
#include "file_manager/file_manager.hpp"
|
||||||
|
|
||||||
#include "app_config.hpp"
|
#include "app_config.hpp"
|
||||||
|
#include "db/sqlite_file_mgr_db.hpp"
|
||||||
#include "file_manager/events.hpp"
|
#include "file_manager/events.hpp"
|
||||||
#include "file_manager/open_file.hpp"
|
#include "file_manager/open_file.hpp"
|
||||||
#include "file_manager/open_file_base.hpp"
|
#include "file_manager/open_file_base.hpp"
|
||||||
#include "file_manager/ring_buffer_open_file.hpp"
|
#include "file_manager/ring_buffer_open_file.hpp"
|
||||||
#include "file_manager/upload.hpp"
|
#include "file_manager/upload.hpp"
|
||||||
|
#include "platform/platform.hpp"
|
||||||
#include "providers/i_provider.hpp"
|
#include "providers/i_provider.hpp"
|
||||||
#include "types/repertory.hpp"
|
#include "types/repertory.hpp"
|
||||||
#include "utils/common.hpp"
|
#include "utils/common.hpp"
|
||||||
#include "utils/db/sqlite/db_common.hpp"
|
|
||||||
#include "utils/db/sqlite/db_delete.hpp"
|
|
||||||
#include "utils/db/sqlite/db_insert.hpp"
|
|
||||||
#include "utils/db/sqlite/db_select.hpp"
|
|
||||||
#include "utils/db/sqlite/db_update.hpp"
|
|
||||||
#include "utils/encrypting_reader.hpp"
|
#include "utils/encrypting_reader.hpp"
|
||||||
#include "utils/error_utils.hpp"
|
#include "utils/error_utils.hpp"
|
||||||
#include "utils/file.hpp"
|
#include "utils/file.hpp"
|
||||||
@ -42,85 +39,24 @@
|
|||||||
#include "utils/polling.hpp"
|
#include "utils/polling.hpp"
|
||||||
#include "utils/time.hpp"
|
#include "utils/time.hpp"
|
||||||
|
|
||||||
namespace {
|
|
||||||
[[nodiscard]] auto
|
|
||||||
create_resume_entry(const repertory::i_open_file &file) -> json {
|
|
||||||
return {
|
|
||||||
{"chunk_size", file.get_chunk_size()},
|
|
||||||
{"path", file.get_api_path()},
|
|
||||||
{"read_state",
|
|
||||||
repertory::utils::string::from_dynamic_bitset(file.get_read_state())},
|
|
||||||
{"source", file.get_source_path()},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void restore_resume_entry(const json &resume_entry, std::string &api_path,
|
|
||||||
std::size_t &chunk_size,
|
|
||||||
boost::dynamic_bitset<> &read_state,
|
|
||||||
std::string &source_path) {
|
|
||||||
api_path = resume_entry["path"].get<std::string>();
|
|
||||||
chunk_size = resume_entry["chunk_size"].get<std::size_t>();
|
|
||||||
read_state = repertory::utils::string::to_dynamic_bitset(
|
|
||||||
resume_entry["read_state"].get<std::string>());
|
|
||||||
source_path = resume_entry["source"].get<std::string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string resume_table = "resume";
|
|
||||||
const std::string upload_table = "upload";
|
|
||||||
const std::string upload_active_table = "upload_active";
|
|
||||||
const std::map<std::string, std::string> sql_create_tables{
|
|
||||||
{
|
|
||||||
{resume_table},
|
|
||||||
{
|
|
||||||
"CREATE TABLE IF NOT EXISTS " + resume_table +
|
|
||||||
"("
|
|
||||||
"api_path TEXT PRIMARY KEY ASC, "
|
|
||||||
"data TEXT"
|
|
||||||
");",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{upload_table},
|
|
||||||
{
|
|
||||||
"CREATE TABLE IF NOT EXISTS " + upload_table +
|
|
||||||
"("
|
|
||||||
"api_path TEXT PRIMARY KEY ASC, "
|
|
||||||
"date_time INTEGER, "
|
|
||||||
"source_path TEXT"
|
|
||||||
");",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{upload_active_table},
|
|
||||||
{
|
|
||||||
"CREATE TABLE IF NOT EXISTS " + upload_active_table +
|
|
||||||
"("
|
|
||||||
"api_path TEXT PRIMARY KEY ASC, "
|
|
||||||
"source_path TEXT"
|
|
||||||
");",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
file_manager::file_manager(app_config &config, i_provider &provider)
|
file_manager::file_manager(app_config &config, i_provider &provider)
|
||||||
: config_(config), provider_(provider) {
|
: config_(config), provider_(provider) {
|
||||||
db_ = utils::db::sqlite::create_db(
|
mgr_db_ = std::make_unique<sqlite_file_mgr_db>(config_);
|
||||||
utils::path::combine(config_.get_data_directory(), {"file_manager.db"}),
|
|
||||||
sql_create_tables);
|
if (provider_.is_read_only()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (not provider_.is_read_only()) {
|
|
||||||
E_SUBSCRIBE_EXACT(file_upload_completed,
|
E_SUBSCRIBE_EXACT(file_upload_completed,
|
||||||
[this](const file_upload_completed &completed) {
|
[this](const file_upload_completed &completed) {
|
||||||
this->upload_completed(completed);
|
this->upload_completed(completed);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
file_manager::~file_manager() {
|
file_manager::~file_manager() {
|
||||||
stop();
|
stop();
|
||||||
db_.reset();
|
mgr_db_.reset();
|
||||||
|
|
||||||
E_CONSUMER_RELEASE();
|
E_CONSUMER_RELEASE();
|
||||||
}
|
}
|
||||||
@ -336,32 +272,15 @@ auto file_manager::get_open_handle_count() const -> std::size_t {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
auto file_manager::get_stored_downloads() const -> std::vector<json> {
|
auto file_manager::get_stored_downloads() const
|
||||||
|
-> std::vector<i_file_mgr_db::resume_entry> {
|
||||||
REPERTORY_USES_FUNCTION_NAME();
|
REPERTORY_USES_FUNCTION_NAME();
|
||||||
|
|
||||||
if (provider_.is_read_only()) {
|
if (provider_.is_read_only()) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<json> ret;
|
return mgr_db_->get_resume_list();
|
||||||
auto result = utils::db::sqlite::db_select{*db_, resume_table}.go();
|
|
||||||
while (result.has_row()) {
|
|
||||||
try {
|
|
||||||
std::optional<utils::db::sqlite::db_result::row> row;
|
|
||||||
if (not result.get_row(row)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (not row.has_value()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.push_back(row.value().get_column("data").get_value_as_json());
|
|
||||||
} catch (const std::exception &ex) {
|
|
||||||
utils::error::raise_error(function_name, ex, "query error");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto file_manager::handle_file_rename(const std::string &from_api_path,
|
auto file_manager::handle_file_rename(const std::string &from_api_path,
|
||||||
@ -379,15 +298,10 @@ auto file_manager::handle_file_rename(const std::string &from_api_path,
|
|||||||
source_path = upload_lookup_.at(from_api_path)->get_source_path();
|
source_path = upload_lookup_.at(from_api_path)->get_source_path();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
auto result = utils::db::sqlite::db_select{*db_, upload_table}
|
auto upload = mgr_db_->get_upload(from_api_path);
|
||||||
.column("source_path")
|
should_upload = upload.has_value();
|
||||||
.where("api_path")
|
|
||||||
.equals(from_api_path)
|
|
||||||
.go();
|
|
||||||
std::optional<utils::db::sqlite::db_result::row> row;
|
|
||||||
should_upload = result.get_row(row) && row.has_value();
|
|
||||||
if (should_upload && source_path.empty()) {
|
if (should_upload && source_path.empty()) {
|
||||||
source_path = row->get_column("source_path").get_value<std::string>();
|
source_path = upload->source_path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,8 +341,8 @@ auto file_manager::is_processing(const std::string &api_path) const -> bool {
|
|||||||
}
|
}
|
||||||
upload_lock.unlock();
|
upload_lock.unlock();
|
||||||
|
|
||||||
utils::db::sqlite::db_select query{*db_, upload_table};
|
auto upload = mgr_db_->get_upload(api_path);
|
||||||
if (query.where("api_path").equals(api_path).go().has_row()) {
|
if (upload.has_value()) {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -510,21 +424,16 @@ void file_manager::queue_upload(const std::string &api_path,
|
|||||||
|
|
||||||
remove_upload(api_path, true);
|
remove_upload(api_path, true);
|
||||||
|
|
||||||
auto result =
|
if (mgr_db_->add_upload({
|
||||||
utils::db::sqlite::db_insert{*db_, upload_table}
|
api_path,
|
||||||
.or_replace()
|
utils::time::get_time_now(),
|
||||||
.column_value("api_path", api_path)
|
source_path,
|
||||||
.column_value("date_time",
|
})) {
|
||||||
static_cast<std::int64_t>(utils::time::get_time_now()))
|
|
||||||
.column_value("source_path", source_path)
|
|
||||||
.go();
|
|
||||||
if (result.ok()) {
|
|
||||||
remove_resume(api_path, source_path);
|
remove_resume(api_path, source_path);
|
||||||
event_system::instance().raise<file_upload_queued>(api_path, source_path);
|
event_system::instance().raise<file_upload_queued>(api_path, source_path);
|
||||||
} else {
|
} else {
|
||||||
event_system::instance().raise<file_upload_failed>(
|
event_system::instance().raise<file_upload_failed>(
|
||||||
api_path, source_path,
|
api_path, source_path, "failed to queue upload");
|
||||||
std::to_string(result.get_error()) + '|' + result.get_error_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not no_lock) {
|
if (not no_lock) {
|
||||||
@ -561,14 +470,12 @@ auto file_manager::remove_file(const std::string &api_path) -> api_error {
|
|||||||
|
|
||||||
void file_manager::remove_resume(const std::string &api_path,
|
void file_manager::remove_resume(const std::string &api_path,
|
||||||
const std::string &source_path) {
|
const std::string &source_path) {
|
||||||
auto result = utils::db::sqlite::db_delete{*db_, resume_table}
|
if (not mgr_db_->remove_resume(api_path)) {
|
||||||
.where("api_path")
|
return;
|
||||||
.equals(api_path)
|
}
|
||||||
.go();
|
|
||||||
if (result.ok()) {
|
|
||||||
event_system::instance().raise<download_resume_removed>(api_path,
|
event_system::instance().raise<download_resume_removed>(api_path,
|
||||||
source_path);
|
source_path);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void file_manager::remove_upload(const std::string &api_path) {
|
void file_manager::remove_upload(const std::string &api_path) {
|
||||||
@ -587,21 +494,13 @@ void file_manager::remove_upload(const std::string &api_path, bool no_lock) {
|
|||||||
lock = std::make_unique<mutex_lock>(upload_mtx_);
|
lock = std::make_unique<mutex_lock>(upload_mtx_);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = utils::db::sqlite::db_delete{*db_, upload_table}
|
if (not mgr_db_->remove_upload(api_path)) {
|
||||||
.where("api_path")
|
utils::error::raise_api_path_error(
|
||||||
.equals(api_path)
|
function_name, api_path, api_error::error, "failed to remove upload");
|
||||||
.go();
|
|
||||||
if (not result.ok()) {
|
|
||||||
utils::error::raise_api_path_error(function_name, api_path,
|
|
||||||
api_error::error,
|
|
||||||
"failed to remove from upload table");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = utils::db::sqlite::db_delete{*db_, upload_active_table}
|
auto removed = not mgr_db_->remove_upload_active(api_path);
|
||||||
.where("api_path")
|
if (not removed) {
|
||||||
.equals(api_path)
|
|
||||||
.go();
|
|
||||||
if (not result.ok()) {
|
|
||||||
utils::error::raise_api_path_error(
|
utils::error::raise_api_path_error(
|
||||||
function_name, api_path, api_error::error,
|
function_name, api_path, api_error::error,
|
||||||
"failed to remove from upload_active table");
|
"failed to remove from upload_active table");
|
||||||
@ -612,7 +511,7 @@ void file_manager::remove_upload(const std::string &api_path, bool no_lock) {
|
|||||||
upload_lookup_.erase(api_path);
|
upload_lookup_.erase(api_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.ok()) {
|
if (removed) {
|
||||||
event_system::instance().raise<file_upload_removed>(api_path);
|
event_system::instance().raise<file_upload_removed>(api_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -779,15 +678,6 @@ void file_manager::start() {
|
|||||||
|
|
||||||
stop_requested_ = false;
|
stop_requested_ = false;
|
||||||
|
|
||||||
polling::instance().set_callback({
|
|
||||||
"db_cleanup",
|
|
||||||
polling::frequency::medium,
|
|
||||||
[this](auto && /* stop_requested */) {
|
|
||||||
mutex_lock lock(upload_mtx_);
|
|
||||||
sqlite3_db_release_memory(db_.get());
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
polling::instance().set_callback({
|
polling::instance().set_callback({
|
||||||
"timed_out_close",
|
"timed_out_close",
|
||||||
polling::frequency::second,
|
polling::frequency::second,
|
||||||
@ -799,67 +689,25 @@ void file_manager::start() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct active_item final {
|
for (const auto &entry : mgr_db_->get_upload_active_list()) {
|
||||||
std::string api_path;
|
queue_upload(entry.api_path, entry.source_path, false);
|
||||||
std::string source_path;
|
}
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<active_item> active_items{};
|
for (const auto &entry : mgr_db_->get_resume_list()) {
|
||||||
|
|
||||||
auto result = utils::db::sqlite::db_select{*db_, upload_active_table}.go();
|
|
||||||
while (result.has_row()) {
|
|
||||||
try {
|
try {
|
||||||
std::optional<utils::db::sqlite::db_result::row> row;
|
|
||||||
if (result.get_row(row) && row.has_value()) {
|
|
||||||
active_items.emplace_back(active_item{
|
|
||||||
row->get_column("api_path").get_value<std::string>(),
|
|
||||||
row->get_column("source_path").get_value<std::string>(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (const std::exception &ex) {
|
|
||||||
utils::error::raise_error(function_name, ex, "query error");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &&active_item : active_items) {
|
|
||||||
queue_upload(active_item.api_path, active_item.source_path, false);
|
|
||||||
}
|
|
||||||
active_items.clear();
|
|
||||||
|
|
||||||
result = utils::db::sqlite::db_select{*db_, resume_table}.go();
|
|
||||||
if (not result.ok()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (result.has_row()) {
|
|
||||||
try {
|
|
||||||
std::optional<utils::db::sqlite::db_result::row> row;
|
|
||||||
if (not(result.get_row(row) && row.has_value())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto resume_entry = row.value().get_column("data").get_value_as_json();
|
|
||||||
|
|
||||||
std::string api_path;
|
|
||||||
std::string source_path;
|
|
||||||
std::size_t chunk_size{};
|
|
||||||
boost::dynamic_bitset<> read_state;
|
|
||||||
restore_resume_entry(resume_entry, api_path, chunk_size, read_state,
|
|
||||||
source_path);
|
|
||||||
|
|
||||||
filesystem_item fsi{};
|
filesystem_item fsi{};
|
||||||
auto res = provider_.get_filesystem_item(api_path, false, fsi);
|
auto res = provider_.get_filesystem_item(entry.api_path, false, fsi);
|
||||||
if (res != api_error::success) {
|
if (res != api_error::success) {
|
||||||
event_system::instance().raise<download_restore_failed>(
|
event_system::instance().raise<download_restore_failed>(
|
||||||
api_path, source_path,
|
entry.api_path, entry.source_path,
|
||||||
"failed to get filesystem item|" + api_error_to_string(res));
|
"failed to get filesystem item|" + api_error_to_string(res));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source_path != fsi.source_path) {
|
if (entry.source_path != fsi.source_path) {
|
||||||
event_system::instance().raise<download_restore_failed>(
|
event_system::instance().raise<download_restore_failed>(
|
||||||
fsi.api_path, fsi.source_path,
|
fsi.api_path, fsi.source_path,
|
||||||
"source path mismatch|expected|" + source_path + "|actual|" +
|
"source path mismatch|expected|" + entry.source_path + "|actual|" +
|
||||||
fsi.source_path);
|
fsi.source_path);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -883,12 +731,12 @@ void file_manager::start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto closeable_file = std::make_shared<open_file>(
|
auto closeable_file = std::make_shared<open_file>(
|
||||||
chunk_size,
|
entry.chunk_size,
|
||||||
config_.get_enable_chunk_download_timeout()
|
config_.get_enable_chunk_download_timeout()
|
||||||
? config_.get_chunk_downloader_timeout_secs()
|
? config_.get_chunk_downloader_timeout_secs()
|
||||||
: 0U,
|
: 0U,
|
||||||
fsi, provider_, read_state, *this);
|
fsi, provider_, entry.read_state, *this);
|
||||||
open_file_lookup_[api_path] = closeable_file;
|
open_file_lookup_[entry.api_path] = closeable_file;
|
||||||
event_system::instance().raise<download_restored>(fsi.api_path,
|
event_system::instance().raise<download_restored>(fsi.api_path,
|
||||||
fsi.source_path);
|
fsi.source_path);
|
||||||
} catch (const std::exception &ex) {
|
} catch (const std::exception &ex) {
|
||||||
@ -948,21 +796,19 @@ void file_manager::store_resume(const i_open_file &file) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = utils::db::sqlite::db_insert{*db_, resume_table}
|
if (mgr_db_->add_resume({
|
||||||
.or_replace()
|
file.get_api_path(),
|
||||||
.column_value("api_path", file.get_api_path())
|
file.get_chunk_size(),
|
||||||
.column_value("data", create_resume_entry(file).dump())
|
file.get_read_state(),
|
||||||
.go();
|
file.get_source_path(),
|
||||||
if (result.ok()) {
|
})) {
|
||||||
event_system::instance().raise<download_resume_added>(
|
event_system::instance().raise<download_resume_added>(
|
||||||
file.get_api_path(), file.get_source_path());
|
file.get_api_path(), file.get_source_path());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
event_system::instance().raise<download_resume_add_failed>(
|
event_system::instance().raise<download_resume_add_failed>(
|
||||||
file.get_api_path(), file.get_source_path(),
|
file.get_api_path(), file.get_source_path(), "failed to store resume");
|
||||||
"failed to insert|" + std::to_string(result.get_error()) + '|' +
|
|
||||||
result.get_error_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void file_manager::swap_renamed_items(std::string from_api_path,
|
void file_manager::swap_renamed_items(std::string from_api_path,
|
||||||
@ -981,16 +827,13 @@ void file_manager::swap_renamed_items(std::string from_api_path,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = utils::db::sqlite::db_update{*db_, resume_table}
|
if (mgr_db_->rename_resume(from_api_path, to_api_path)) {
|
||||||
.column_value("api_path", to_api_path)
|
return;
|
||||||
.where("api_path")
|
}
|
||||||
.equals(from_api_path)
|
|
||||||
.go();
|
|
||||||
if (not result.ok()) {
|
|
||||||
utils::error::raise_api_path_error(function_name, to_api_path,
|
utils::error::raise_api_path_error(function_name, to_api_path,
|
||||||
api_error::error,
|
api_error::error,
|
||||||
"failed to update resume table");
|
"failed to update resume table");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void file_manager::upload_completed(const file_upload_completed &evt) {
|
void file_manager::upload_completed(const file_upload_completed &evt) {
|
||||||
@ -1001,11 +844,8 @@ void file_manager::upload_completed(const file_upload_completed &evt) {
|
|||||||
if (not utils::string::to_bool(evt.get_cancelled().get<std::string>())) {
|
if (not utils::string::to_bool(evt.get_cancelled().get<std::string>())) {
|
||||||
auto err = api_error_from_string(evt.get_result().get<std::string>());
|
auto err = api_error_from_string(evt.get_result().get<std::string>());
|
||||||
if (err == api_error::success) {
|
if (err == api_error::success) {
|
||||||
auto result = utils::db::sqlite::db_delete{*db_, upload_active_table}
|
if (not mgr_db_->remove_upload_active(
|
||||||
.where("api_path")
|
evt.get_api_path().get<std::string>())) {
|
||||||
.equals(evt.get_api_path().get<std::string>())
|
|
||||||
.go();
|
|
||||||
if (not result.ok()) {
|
|
||||||
utils::error::raise_api_path_error(
|
utils::error::raise_api_path_error(
|
||||||
function_name, evt.get_api_path().get<std::string>(),
|
function_name, evt.get_api_path().get<std::string>(),
|
||||||
evt.get_source().get<std::string>(),
|
evt.get_source().get<std::string>(),
|
||||||
@ -1046,25 +886,17 @@ void file_manager::upload_handler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (upload_lookup_.size() < config_.get_max_upload_count()) {
|
if (upload_lookup_.size() < config_.get_max_upload_count()) {
|
||||||
auto result = utils::db::sqlite::db_select{*db_, upload_table}
|
|
||||||
.order_by("api_path", true)
|
|
||||||
.limit(1)
|
|
||||||
.go();
|
|
||||||
try {
|
try {
|
||||||
std::optional<utils::db::sqlite::db_result::row> row;
|
auto entry = mgr_db_->get_next_upload();
|
||||||
if (result.get_row(row) && row.has_value()) {
|
if (entry.has_value()) {
|
||||||
auto api_path = row->get_column("api_path").get_value<std::string>();
|
|
||||||
auto source_path =
|
|
||||||
row->get_column("source_path").get_value<std::string>();
|
|
||||||
|
|
||||||
filesystem_item fsi{};
|
filesystem_item fsi{};
|
||||||
auto res = provider_.get_filesystem_item(api_path, false, fsi);
|
auto res = provider_.get_filesystem_item(entry->api_path, false, fsi);
|
||||||
switch (res) {
|
switch (res) {
|
||||||
case api_error::item_not_found: {
|
case api_error::item_not_found: {
|
||||||
should_wait = false;
|
should_wait = false;
|
||||||
event_system::instance().raise<file_upload_not_found>(api_path,
|
event_system::instance().raise<file_upload_not_found>(
|
||||||
source_path);
|
entry->api_path, entry->source_path);
|
||||||
remove_upload(api_path, true);
|
remove_upload(entry->api_path, true);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case api_error::success: {
|
case api_error::success: {
|
||||||
@ -1072,28 +904,22 @@ void file_manager::upload_handler() {
|
|||||||
|
|
||||||
upload_lookup_[fsi.api_path] =
|
upload_lookup_[fsi.api_path] =
|
||||||
std::make_unique<upload>(fsi, provider_);
|
std::make_unique<upload>(fsi, provider_);
|
||||||
auto del_res = utils::db::sqlite::db_delete{*db_, upload_table}
|
if (mgr_db_->remove_upload(entry->api_path)) {
|
||||||
.where("api_path")
|
if (not mgr_db_->add_upload_active({
|
||||||
.equals(api_path)
|
entry->api_path,
|
||||||
.go();
|
entry->source_path,
|
||||||
if (del_res.ok()) {
|
})) {
|
||||||
auto ins_res =
|
|
||||||
utils::db::sqlite::db_insert{*db_, upload_active_table}
|
|
||||||
.column_value("api_path", api_path)
|
|
||||||
.column_value("source_path", source_path)
|
|
||||||
.go();
|
|
||||||
if (not ins_res.ok()) {
|
|
||||||
utils::error::raise_api_path_error(
|
utils::error::raise_api_path_error(
|
||||||
function_name, api_path, source_path,
|
function_name, entry->api_path, entry->source_path,
|
||||||
"failed to add to upload_active table");
|
"failed to add to upload_active table");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
event_system::instance().raise<file_upload_retry>(api_path,
|
event_system::instance().raise<file_upload_retry>(
|
||||||
source_path, res);
|
entry->api_path, entry->source_path, res);
|
||||||
queue_upload(api_path, source_path, true);
|
queue_upload(entry->api_path, entry->source_path, true);
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
#ifndef REPERTORY_TEST_INCLUDE_FIXTURES_FILE_MGR_DB_FIXTURE_HPP
|
||||||
|
#define REPERTORY_TEST_INCLUDE_FIXTURES_FILE_MGR_DB_FIXTURE_HPP
|
||||||
|
|
||||||
|
#include "test_common.hpp"
|
||||||
|
|
||||||
|
#include "app_config.hpp"
|
||||||
|
// #include "db/rdb_meta_db.hpp"
|
||||||
|
#include "db/sqlite_file_mgr_db.hpp"
|
||||||
|
#include "events/consumers/console_consumer.hpp"
|
||||||
|
#include "events/event_system.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
template <typename db_t> class file_mgr_db_test : public ::testing::Test {
|
||||||
|
protected:
|
||||||
|
static std::unique_ptr<app_config> config;
|
||||||
|
static console_consumer console_;
|
||||||
|
static std::unique_ptr<db_t> file_mgr_db;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void SetUpTestCase() {
|
||||||
|
static std::uint64_t idx{};
|
||||||
|
|
||||||
|
event_system::instance().start();
|
||||||
|
auto cfg_directory = utils::path::combine(test::get_test_output_dir(),
|
||||||
|
{
|
||||||
|
"file_mgr_db_test",
|
||||||
|
std::to_string(++idx),
|
||||||
|
});
|
||||||
|
config = std::make_unique<app_config>(provider_type::s3, cfg_directory);
|
||||||
|
file_mgr_db = std::make_unique<db_t>(*config);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TearDownTestCase() {
|
||||||
|
file_mgr_db.reset();
|
||||||
|
config.reset();
|
||||||
|
event_system::instance().stop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using file_mgr_db_types = ::testing::Types<sqlite_file_mgr_db>;
|
||||||
|
|
||||||
|
template <typename db_t>
|
||||||
|
std::unique_ptr<app_config> file_mgr_db_test<db_t>::config;
|
||||||
|
|
||||||
|
template <typename db_t> console_consumer file_mgr_db_test<db_t>::console_;
|
||||||
|
|
||||||
|
template <typename db_t>
|
||||||
|
std::unique_ptr<db_t> file_mgr_db_test<db_t>::file_mgr_db;
|
||||||
|
} // namespace repertory
|
||||||
|
|
||||||
|
#endif // REPERTORY_TEST_INCLUDE_FIXTURES_FILE_MGR_DB_FIXTURE_HPP
|
@ -496,20 +496,17 @@ TEST_F(file_manager_test,
|
|||||||
|
|
||||||
auto stored_downloads = mgr.get_stored_downloads();
|
auto stored_downloads = mgr.get_stored_downloads();
|
||||||
EXPECT_EQ(std::size_t(1u), stored_downloads.size());
|
EXPECT_EQ(std::size_t(1u), stored_downloads.size());
|
||||||
std::cout << stored_downloads[0u].dump(2) << std::endl;
|
|
||||||
|
|
||||||
EXPECT_STREQ("/test_write_partial_download.txt",
|
EXPECT_STREQ("/test_write_partial_download.txt",
|
||||||
stored_downloads[0u]["path"].get<std::string>().c_str());
|
stored_downloads[0U].api_path.c_str());
|
||||||
EXPECT_EQ(utils::encryption::encrypting_reader::get_data_chunk_size(),
|
EXPECT_EQ(utils::encryption::encrypting_reader::get_data_chunk_size(),
|
||||||
stored_downloads[0u]["chunk_size"].get<std::size_t>());
|
stored_downloads[0U].chunk_size);
|
||||||
auto read_state = utils::string::to_dynamic_bitset(
|
auto read_state = stored_downloads[0U].read_state;
|
||||||
stored_downloads[0u]["read_state"].get<std::string>());
|
EXPECT_TRUE(read_state[0U]);
|
||||||
EXPECT_TRUE(read_state[0u]);
|
for (std::size_t i = 1U; i < read_state.size(); i++) {
|
||||||
for (std::size_t i = 1u; i < read_state.size(); i++) {
|
|
||||||
EXPECT_FALSE(read_state[i]);
|
EXPECT_FALSE(read_state[i]);
|
||||||
}
|
}
|
||||||
EXPECT_STREQ(source_path.c_str(),
|
EXPECT_STREQ(source_path.c_str(), stored_downloads[0u].source_path.c_str());
|
||||||
stored_downloads[0u]["source"].get<std::string>().c_str());
|
|
||||||
|
|
||||||
mgr.start();
|
mgr.start();
|
||||||
|
|
||||||
|
96
repertory/repertory_test/src/file_mgr_db_test.cpp
Normal file
96
repertory/repertory_test/src/file_mgr_db_test.cpp
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "fixtures/file_mgr_db_fixture.hpp"
|
||||||
|
|
||||||
|
namespace repertory {
|
||||||
|
TYPED_TEST_CASE(file_mgr_db_test, file_mgr_db_types);
|
||||||
|
|
||||||
|
TYPED_TEST(file_mgr_db_test, can_add_and_remove_resume) {
|
||||||
|
this->file_mgr_db->clear();
|
||||||
|
|
||||||
|
EXPECT_TRUE(this->file_mgr_db->add_resume({
|
||||||
|
"/test0",
|
||||||
|
2ULL,
|
||||||
|
{},
|
||||||
|
"/src/test0",
|
||||||
|
}));
|
||||||
|
auto list = this->file_mgr_db->get_resume_list();
|
||||||
|
EXPECT_EQ(1U, list.size());
|
||||||
|
EXPECT_EQ(1U, list.size());
|
||||||
|
EXPECT_STREQ("/test0", list.at(0U).api_path.c_str());
|
||||||
|
EXPECT_EQ(2ULL, list.at(0U).chunk_size);
|
||||||
|
EXPECT_STREQ("/src/test0", list.at(0U).source_path.c_str());
|
||||||
|
|
||||||
|
EXPECT_TRUE(this->file_mgr_db->remove_resume("/test0"));
|
||||||
|
list = this->file_mgr_db->get_resume_list();
|
||||||
|
EXPECT_TRUE(list.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST(file_mgr_db_test, can_get_resume_list) {
|
||||||
|
this->file_mgr_db->clear();
|
||||||
|
|
||||||
|
for (auto idx = 0U; idx < 5U; ++idx) {
|
||||||
|
EXPECT_TRUE(this->file_mgr_db->add_resume({
|
||||||
|
"/test1_" + std::to_string(idx),
|
||||||
|
2ULL + idx,
|
||||||
|
{},
|
||||||
|
"/src/test1_" + std::to_string(idx),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto list = this->file_mgr_db->get_resume_list();
|
||||||
|
EXPECT_EQ(5U, list.size());
|
||||||
|
for (auto idx = 0U; idx < list.size(); ++idx) {
|
||||||
|
EXPECT_STREQ(("/test1_" + std::to_string(idx)).c_str(),
|
||||||
|
list.at(idx).api_path.c_str());
|
||||||
|
EXPECT_EQ(2ULL + idx, list.at(idx).chunk_size);
|
||||||
|
EXPECT_STREQ(("/src/test1_" + std::to_string(idx)).c_str(),
|
||||||
|
list.at(idx).source_path.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPED_TEST(file_mgr_db_test, can_replace_resume) {
|
||||||
|
this->file_mgr_db->clear();
|
||||||
|
|
||||||
|
EXPECT_TRUE(this->file_mgr_db->add_resume({
|
||||||
|
"/test0",
|
||||||
|
2ULL,
|
||||||
|
{},
|
||||||
|
"/src/test0",
|
||||||
|
}));
|
||||||
|
EXPECT_TRUE(this->file_mgr_db->add_resume({
|
||||||
|
"/test0",
|
||||||
|
3ULL,
|
||||||
|
{},
|
||||||
|
"/src/test1",
|
||||||
|
}));
|
||||||
|
|
||||||
|
auto list = this->file_mgr_db->get_resume_list();
|
||||||
|
EXPECT_EQ(1U, list.size());
|
||||||
|
EXPECT_STREQ("/test0", list.at(0U).api_path.c_str());
|
||||||
|
EXPECT_EQ(3ULL, list.at(0U).chunk_size);
|
||||||
|
EXPECT_STREQ("/src/test1", list.at(0U).source_path.c_str());
|
||||||
|
|
||||||
|
EXPECT_TRUE(this->file_mgr_db->remove_resume("/test0"));
|
||||||
|
}
|
||||||
|
} // namespace repertory
|
Loading…
x
Reference in New Issue
Block a user