refactor
This commit is contained in:
parent
48a1bef1ae
commit
ad79c5daf5
@ -27,6 +27,7 @@
|
||||
#include "file_manager/i_file_manager.hpp"
|
||||
#include "file_manager/i_open_file.hpp"
|
||||
#include "file_manager/i_upload_manager.hpp"
|
||||
#include "file_manager/upload.hpp"
|
||||
#include "platform/platform.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/db/sqlite/db_common.hpp"
|
||||
@ -39,408 +40,6 @@ class i_provider;
|
||||
class file_manager final : public i_file_manager, public i_upload_manager {
|
||||
E_CONSUMER();
|
||||
|
||||
public:
|
||||
class open_file_base : public i_closeable_open_file {
|
||||
public:
|
||||
open_file_base(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi, i_provider &provider);
|
||||
|
||||
open_file_base(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi,
|
||||
std::map<std::uint64_t, open_file_data> open_data,
|
||||
i_provider &provider);
|
||||
|
||||
~open_file_base() override = default;
|
||||
|
||||
public:
|
||||
open_file_base() = delete;
|
||||
open_file_base(const open_file_base &) noexcept = delete;
|
||||
open_file_base(open_file_base &&) noexcept = delete;
|
||||
auto operator=(open_file_base &&) noexcept -> open_file_base & = delete;
|
||||
auto operator=(const open_file_base &) noexcept
|
||||
-> open_file_base & = delete;
|
||||
|
||||
public:
|
||||
class download final {
|
||||
public:
|
||||
download() = default;
|
||||
|
||||
~download() = default;
|
||||
|
||||
public:
|
||||
download(const download &) noexcept = delete;
|
||||
download(download &&) noexcept = delete;
|
||||
auto operator=(download &&) noexcept -> download & = delete;
|
||||
auto operator=(const download &) noexcept -> download & = delete;
|
||||
|
||||
private:
|
||||
bool complete_{false};
|
||||
api_error error_{api_error::success};
|
||||
std::mutex mtx_;
|
||||
std::condition_variable notify_;
|
||||
|
||||
public:
|
||||
void notify(const api_error &err);
|
||||
|
||||
auto wait() -> api_error;
|
||||
};
|
||||
|
||||
class io_item final {
|
||||
public:
|
||||
io_item(std::function<api_error()> action) : action_(std::move(action)) {}
|
||||
|
||||
~io_item() = default;
|
||||
|
||||
public:
|
||||
io_item() = delete;
|
||||
io_item(const io_item &) noexcept = delete;
|
||||
io_item(io_item &&) noexcept = delete;
|
||||
auto operator=(io_item &&) noexcept -> io_item & = delete;
|
||||
auto operator=(const io_item &) noexcept -> io_item & = delete;
|
||||
|
||||
private:
|
||||
std::function<api_error()> action_;
|
||||
std::mutex mtx_;
|
||||
std::condition_variable notify_;
|
||||
std::optional<api_error> result_;
|
||||
|
||||
public:
|
||||
void action();
|
||||
|
||||
[[nodiscard]] auto get_result() -> api_error;
|
||||
};
|
||||
|
||||
protected:
|
||||
std::uint64_t chunk_size_;
|
||||
std::uint8_t chunk_timeout_;
|
||||
filesystem_item fsi_;
|
||||
std::size_t last_chunk_size_;
|
||||
std::map<std::uint64_t, open_file_data> open_data_;
|
||||
i_provider &provider_;
|
||||
|
||||
private:
|
||||
api_error error_{api_error::success};
|
||||
mutable std::mutex error_mtx_;
|
||||
stop_type io_stop_requested_{false};
|
||||
std::unique_ptr<std::thread> io_thread_;
|
||||
|
||||
protected:
|
||||
std::unordered_map<std::size_t, std::shared_ptr<download>>
|
||||
active_downloads_;
|
||||
mutable std::recursive_mutex file_mtx_;
|
||||
std::atomic<std::chrono::system_clock::time_point> last_access_{
|
||||
std::chrono::system_clock::now()};
|
||||
bool modified_{false};
|
||||
std::unique_ptr<utils::file::i_file> nf_;
|
||||
mutable std::mutex io_thread_mtx_;
|
||||
std::condition_variable io_thread_notify_;
|
||||
std::deque<std::shared_ptr<io_item>> io_thread_queue_;
|
||||
bool removed_{false};
|
||||
|
||||
private:
|
||||
void file_io_thread();
|
||||
|
||||
protected:
|
||||
[[nodiscard]] auto do_io(std::function<api_error()> action) -> api_error;
|
||||
|
||||
virtual auto is_download_complete() const -> bool = 0;
|
||||
|
||||
void reset_timeout();
|
||||
|
||||
auto set_api_error(const api_error &e) -> api_error;
|
||||
|
||||
public:
|
||||
void add(std::uint64_t handle, open_file_data ofd) override;
|
||||
|
||||
[[nodiscard]] auto can_close() const -> bool override;
|
||||
|
||||
auto close() -> bool override;
|
||||
|
||||
[[nodiscard]] auto get_api_error() const -> api_error;
|
||||
|
||||
[[nodiscard]] auto get_api_path() const -> std::string override;
|
||||
|
||||
[[nodiscard]] auto get_chunk_size() const -> std::size_t override {
|
||||
return chunk_size_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_file_size() const -> std::uint64_t override;
|
||||
|
||||
[[nodiscard]] auto get_filesystem_item() const -> filesystem_item override;
|
||||
|
||||
[[nodiscard]] auto get_handles() const
|
||||
-> std::vector<std::uint64_t> override;
|
||||
|
||||
[[nodiscard]] auto get_open_data()
|
||||
-> std::map<std::uint64_t, open_file_data> & override;
|
||||
|
||||
[[nodiscard]] auto get_open_data() const
|
||||
-> const std::map<std::uint64_t, open_file_data> & override;
|
||||
|
||||
[[nodiscard]] auto get_open_data(std::uint64_t handle)
|
||||
-> open_file_data & override;
|
||||
|
||||
[[nodiscard]] auto get_open_data(std::uint64_t handle) const
|
||||
-> const open_file_data & override;
|
||||
|
||||
[[nodiscard]] auto get_open_file_count() const -> std::size_t override;
|
||||
|
||||
[[nodiscard]] auto get_source_path() const -> std::string override {
|
||||
return fsi_.source_path;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto has_handle(std::uint64_t handle) const -> bool override {
|
||||
return open_data_.find(handle) != open_data_.end();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto is_directory() const -> bool override {
|
||||
return fsi_.directory;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto is_modified() const -> bool override;
|
||||
|
||||
void remove(std::uint64_t handle) override;
|
||||
|
||||
void set_api_path(const std::string &api_path) override;
|
||||
};
|
||||
|
||||
class open_file final : public open_file_base {
|
||||
public:
|
||||
open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi, i_provider &provider, i_upload_manager &mgr);
|
||||
|
||||
open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi,
|
||||
std::map<std::uint64_t, open_file_data> open_data,
|
||||
i_provider &provider, i_upload_manager &mgr);
|
||||
|
||||
open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi, i_provider &provider,
|
||||
std::optional<boost::dynamic_bitset<>> read_state,
|
||||
i_upload_manager &mgr);
|
||||
|
||||
private:
|
||||
open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi,
|
||||
std::map<std::uint64_t, open_file_data> open_data,
|
||||
i_provider &provider,
|
||||
std::optional<boost::dynamic_bitset<>> read_state,
|
||||
i_upload_manager &mgr);
|
||||
|
||||
public:
|
||||
open_file() = delete;
|
||||
open_file(const open_file &) noexcept = delete;
|
||||
open_file(open_file &&) noexcept = delete;
|
||||
auto operator=(open_file &&) noexcept -> open_file & = delete;
|
||||
auto operator=(const open_file &) noexcept -> open_file & = delete;
|
||||
|
||||
public:
|
||||
~open_file() override;
|
||||
|
||||
private:
|
||||
i_upload_manager &mgr_;
|
||||
|
||||
private:
|
||||
bool notified_ = false;
|
||||
std::size_t read_chunk_index_{};
|
||||
boost::dynamic_bitset<> read_state_;
|
||||
std::unique_ptr<std::thread> reader_thread_;
|
||||
std::unique_ptr<std::thread> download_thread_;
|
||||
stop_type stop_requested_ = false;
|
||||
|
||||
private:
|
||||
void download_chunk(std::size_t chunk, bool skip_active, bool should_reset);
|
||||
|
||||
void download_range(std::size_t start_chunk_index,
|
||||
std::size_t end_chunk_index_inclusive,
|
||||
bool should_reset);
|
||||
|
||||
void set_modified();
|
||||
|
||||
void update_background_reader(std::size_t read_chunk);
|
||||
|
||||
protected:
|
||||
auto is_download_complete() const -> bool override {
|
||||
return read_state_.all();
|
||||
}
|
||||
|
||||
public:
|
||||
auto close() -> bool override;
|
||||
|
||||
[[nodiscard]] auto get_read_state() const
|
||||
-> boost::dynamic_bitset<> override;
|
||||
|
||||
[[nodiscard]] auto get_read_state(std::size_t chunk) const -> bool override;
|
||||
|
||||
[[nodiscard]] auto is_complete() const -> bool override;
|
||||
|
||||
auto is_write_supported() const -> bool override { return true; }
|
||||
|
||||
[[nodiscard]] auto native_operation(native_operation_callback callback)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto native_operation(std::uint64_t new_file_size,
|
||||
native_operation_callback callback)
|
||||
-> api_error override;
|
||||
|
||||
void remove(std::uint64_t handle) override;
|
||||
|
||||
[[nodiscard]] auto read(std::size_t read_size, std::uint64_t read_offset,
|
||||
data_buffer &data) -> api_error override;
|
||||
|
||||
[[nodiscard]] auto resize(std::uint64_t new_file_size)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto write(std::uint64_t write_offset,
|
||||
const data_buffer &data,
|
||||
std::size_t &bytes_written) -> api_error override;
|
||||
};
|
||||
|
||||
class ring_buffer_open_file final : public open_file_base {
|
||||
public:
|
||||
ring_buffer_open_file(std::string buffer_directory,
|
||||
std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi, i_provider &provider);
|
||||
|
||||
ring_buffer_open_file(std::string buffer_directory,
|
||||
std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi, i_provider &provider,
|
||||
std::size_t ring_size);
|
||||
|
||||
~ring_buffer_open_file() override;
|
||||
|
||||
public:
|
||||
ring_buffer_open_file() = delete;
|
||||
ring_buffer_open_file(const ring_buffer_open_file &) noexcept = delete;
|
||||
ring_buffer_open_file(ring_buffer_open_file &&) noexcept = delete;
|
||||
auto operator=(ring_buffer_open_file &&) noexcept
|
||||
-> ring_buffer_open_file & = delete;
|
||||
auto operator=(const ring_buffer_open_file &) noexcept
|
||||
-> ring_buffer_open_file & = delete;
|
||||
|
||||
private:
|
||||
boost::dynamic_bitset<> ring_state_;
|
||||
std::size_t total_chunks_;
|
||||
|
||||
private:
|
||||
std::unique_ptr<std::thread> chunk_forward_thread_;
|
||||
std::unique_ptr<std::thread> chunk_reverse_thread_;
|
||||
std::condition_variable chunk_notify_;
|
||||
mutable std::mutex chunk_mtx_;
|
||||
std::size_t current_chunk_{};
|
||||
std::size_t first_chunk_{};
|
||||
std::size_t last_chunk_;
|
||||
|
||||
private:
|
||||
auto download_chunk(std::size_t chunk) -> api_error;
|
||||
|
||||
void forward_reader_thread(std::size_t count);
|
||||
|
||||
void reverse_reader_thread(std::size_t count);
|
||||
|
||||
protected:
|
||||
auto is_download_complete() const -> bool override;
|
||||
|
||||
public:
|
||||
void forward(std::size_t count);
|
||||
|
||||
[[nodiscard]] auto get_current_chunk() const -> std::size_t {
|
||||
return current_chunk_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_first_chunk() const -> std::size_t {
|
||||
return first_chunk_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_last_chunk() const -> std::size_t {
|
||||
return last_chunk_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_read_state() const
|
||||
-> boost::dynamic_bitset<> override;
|
||||
|
||||
[[nodiscard]] auto get_read_state(std::size_t chunk) const -> bool override;
|
||||
|
||||
[[nodiscard]] auto get_total_chunks() const -> std::size_t {
|
||||
return total_chunks_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto is_complete() const -> bool override { return true; }
|
||||
|
||||
auto is_write_supported() const -> bool override { return false; }
|
||||
|
||||
[[nodiscard]] auto native_operation(native_operation_callback callback)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto native_operation(std::uint64_t,
|
||||
native_operation_callback)
|
||||
-> api_error override {
|
||||
return api_error::not_supported;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto read(std::size_t read_size, std::uint64_t read_offset,
|
||||
data_buffer &data) -> api_error override;
|
||||
|
||||
[[nodiscard]] auto resize(std::uint64_t) -> api_error override {
|
||||
return api_error::not_supported;
|
||||
}
|
||||
|
||||
void reverse(std::size_t count);
|
||||
|
||||
void set(std::size_t first_chunk, std::size_t current_chunk);
|
||||
|
||||
void set_api_path(const std::string &api_path) override;
|
||||
|
||||
[[nodiscard]] auto write(std::uint64_t, const data_buffer &, std::size_t &)
|
||||
-> api_error override {
|
||||
return api_error::not_supported;
|
||||
}
|
||||
};
|
||||
|
||||
class upload final {
|
||||
public:
|
||||
upload(filesystem_item fsi, i_provider &provider);
|
||||
|
||||
~upload();
|
||||
|
||||
public:
|
||||
upload() = delete;
|
||||
upload(const upload &) noexcept = delete;
|
||||
upload(upload &&) noexcept = delete;
|
||||
auto operator=(upload &&) noexcept -> upload & = delete;
|
||||
auto operator=(const upload &) noexcept -> upload & = delete;
|
||||
|
||||
private:
|
||||
filesystem_item fsi_;
|
||||
i_provider &provider_;
|
||||
|
||||
private:
|
||||
bool cancelled_{false};
|
||||
api_error error_{api_error::success};
|
||||
std::unique_ptr<std::thread> thread_;
|
||||
stop_type stop_requested_{false};
|
||||
|
||||
private:
|
||||
void upload_thread();
|
||||
|
||||
public:
|
||||
void cancel();
|
||||
|
||||
[[nodiscard]] auto get_api_error() const -> api_error { return error_; }
|
||||
|
||||
[[nodiscard]] auto get_api_path() const -> std::string {
|
||||
return fsi_.api_path;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_source_path() const -> std::string {
|
||||
return fsi_.source_path;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto is_cancelled() const -> bool { return cancelled_; }
|
||||
|
||||
void stop();
|
||||
};
|
||||
|
||||
public:
|
||||
file_manager(app_config &config, i_provider &provider);
|
||||
|
||||
|
122
repertory/librepertory/include/file_manager/open_file.hpp
Normal file
122
repertory/librepertory/include/file_manager/open_file.hpp
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef REPERTORY_INCLUDE_FILE_MANAGER_OPEN_FILE_HPP_
|
||||
#define REPERTORY_INCLUDE_FILE_MANAGER_OPEN_FILE_HPP_
|
||||
|
||||
#include "file_manager/open_file_base.hpp"
|
||||
|
||||
#include "types/repertory.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class i_provider;
|
||||
class i_upload_manager;
|
||||
|
||||
class open_file final : public open_file_base {
|
||||
public:
|
||||
open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi, i_provider &provider, i_upload_manager &mgr);
|
||||
|
||||
open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi,
|
||||
std::map<std::uint64_t, open_file_data> open_data,
|
||||
i_provider &provider, i_upload_manager &mgr);
|
||||
|
||||
open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi, i_provider &provider,
|
||||
std::optional<boost::dynamic_bitset<>> read_state,
|
||||
i_upload_manager &mgr);
|
||||
|
||||
private:
|
||||
open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi,
|
||||
std::map<std::uint64_t, open_file_data> open_data,
|
||||
i_provider &provider,
|
||||
std::optional<boost::dynamic_bitset<>> read_state,
|
||||
i_upload_manager &mgr);
|
||||
|
||||
public:
|
||||
open_file() = delete;
|
||||
open_file(const open_file &) noexcept = delete;
|
||||
open_file(open_file &&) noexcept = delete;
|
||||
auto operator=(open_file &&) noexcept -> open_file & = delete;
|
||||
auto operator=(const open_file &) noexcept -> open_file & = delete;
|
||||
|
||||
public:
|
||||
~open_file() override;
|
||||
|
||||
private:
|
||||
i_upload_manager &mgr_;
|
||||
|
||||
private:
|
||||
bool notified_ = false;
|
||||
std::size_t read_chunk_index_{};
|
||||
boost::dynamic_bitset<> read_state_;
|
||||
std::unique_ptr<std::thread> reader_thread_;
|
||||
std::unique_ptr<std::thread> download_thread_;
|
||||
stop_type stop_requested_ = false;
|
||||
|
||||
private:
|
||||
void download_chunk(std::size_t chunk, bool skip_active, bool should_reset);
|
||||
|
||||
void download_range(std::size_t start_chunk_index,
|
||||
std::size_t end_chunk_index_inclusive, bool should_reset);
|
||||
|
||||
void set_modified();
|
||||
|
||||
void update_background_reader(std::size_t read_chunk);
|
||||
|
||||
protected:
|
||||
auto is_download_complete() const -> bool override {
|
||||
return read_state_.all();
|
||||
}
|
||||
|
||||
public:
|
||||
auto close() -> bool override;
|
||||
|
||||
[[nodiscard]] auto get_read_state() const -> boost::dynamic_bitset<> override;
|
||||
|
||||
[[nodiscard]] auto get_read_state(std::size_t chunk) const -> bool override;
|
||||
|
||||
[[nodiscard]] auto is_complete() const -> bool override;
|
||||
|
||||
auto is_write_supported() const -> bool override { return true; }
|
||||
|
||||
[[nodiscard]] auto native_operation(native_operation_callback callback)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto native_operation(std::uint64_t new_file_size,
|
||||
native_operation_callback callback)
|
||||
-> api_error override;
|
||||
|
||||
void remove(std::uint64_t handle) override;
|
||||
|
||||
[[nodiscard]] auto read(std::size_t read_size, std::uint64_t read_offset,
|
||||
data_buffer &data) -> api_error override;
|
||||
|
||||
[[nodiscard]] auto resize(std::uint64_t new_file_size) -> api_error override;
|
||||
|
||||
[[nodiscard]] auto write(std::uint64_t write_offset, const data_buffer &data,
|
||||
std::size_t &bytes_written) -> api_error override;
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // REPERTORY_INCLUDE_FILE_MANAGER_OPEN_FILE_HPP_
|
194
repertory/librepertory/include/file_manager/open_file_base.hpp
Normal file
194
repertory/librepertory/include/file_manager/open_file_base.hpp
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef REPERTORY_INCLUDE_FILE_MANAGER_OPEN_FILE_BASE_HPP_
|
||||
#define REPERTORY_INCLUDE_FILE_MANAGER_OPEN_FILE_BASE_HPP_
|
||||
|
||||
#include "file_manager/i_open_file.hpp"
|
||||
|
||||
#include "utils/types/file/i_file.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class i_provider;
|
||||
|
||||
class open_file_base : public i_closeable_open_file {
|
||||
public:
|
||||
open_file_base(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi, i_provider &provider);
|
||||
|
||||
open_file_base(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi,
|
||||
std::map<std::uint64_t, open_file_data> open_data,
|
||||
i_provider &provider);
|
||||
|
||||
~open_file_base() override = default;
|
||||
|
||||
public:
|
||||
open_file_base() = delete;
|
||||
open_file_base(const open_file_base &) noexcept = delete;
|
||||
open_file_base(open_file_base &&) noexcept = delete;
|
||||
auto operator=(open_file_base &&) noexcept -> open_file_base & = delete;
|
||||
auto operator=(const open_file_base &) noexcept -> open_file_base & = delete;
|
||||
|
||||
public:
|
||||
class download final {
|
||||
public:
|
||||
download() = default;
|
||||
|
||||
~download() = default;
|
||||
|
||||
public:
|
||||
download(const download &) noexcept = delete;
|
||||
download(download &&) noexcept = delete;
|
||||
auto operator=(download &&) noexcept -> download & = delete;
|
||||
auto operator=(const download &) noexcept -> download & = delete;
|
||||
|
||||
private:
|
||||
bool complete_{false};
|
||||
api_error error_{api_error::success};
|
||||
std::mutex mtx_;
|
||||
std::condition_variable notify_;
|
||||
|
||||
public:
|
||||
void notify(const api_error &err);
|
||||
|
||||
auto wait() -> api_error;
|
||||
};
|
||||
|
||||
class io_item final {
|
||||
public:
|
||||
io_item(std::function<api_error()> action) : action_(std::move(action)) {}
|
||||
|
||||
~io_item() = default;
|
||||
|
||||
public:
|
||||
io_item() = delete;
|
||||
io_item(const io_item &) noexcept = delete;
|
||||
io_item(io_item &&) noexcept = delete;
|
||||
auto operator=(io_item &&) noexcept -> io_item & = delete;
|
||||
auto operator=(const io_item &) noexcept -> io_item & = delete;
|
||||
|
||||
private:
|
||||
std::function<api_error()> action_;
|
||||
std::mutex mtx_;
|
||||
std::condition_variable notify_;
|
||||
std::optional<api_error> result_;
|
||||
|
||||
public:
|
||||
void action();
|
||||
|
||||
[[nodiscard]] auto get_result() -> api_error;
|
||||
};
|
||||
|
||||
protected:
|
||||
std::uint64_t chunk_size_;
|
||||
std::uint8_t chunk_timeout_;
|
||||
filesystem_item fsi_;
|
||||
std::size_t last_chunk_size_;
|
||||
std::map<std::uint64_t, open_file_data> open_data_;
|
||||
i_provider &provider_;
|
||||
|
||||
private:
|
||||
api_error error_{api_error::success};
|
||||
mutable std::mutex error_mtx_;
|
||||
stop_type io_stop_requested_{false};
|
||||
std::unique_ptr<std::thread> io_thread_;
|
||||
|
||||
protected:
|
||||
std::unordered_map<std::size_t, std::shared_ptr<download>> active_downloads_;
|
||||
mutable std::recursive_mutex file_mtx_;
|
||||
std::atomic<std::chrono::system_clock::time_point> last_access_{
|
||||
std::chrono::system_clock::now()};
|
||||
bool modified_{false};
|
||||
std::unique_ptr<utils::file::i_file> nf_;
|
||||
mutable std::mutex io_thread_mtx_;
|
||||
std::condition_variable io_thread_notify_;
|
||||
std::deque<std::shared_ptr<io_item>> io_thread_queue_;
|
||||
bool removed_{false};
|
||||
|
||||
private:
|
||||
void file_io_thread();
|
||||
|
||||
protected:
|
||||
[[nodiscard]] auto do_io(std::function<api_error()> action) -> api_error;
|
||||
|
||||
virtual auto is_download_complete() const -> bool = 0;
|
||||
|
||||
void reset_timeout();
|
||||
|
||||
auto set_api_error(const api_error &e) -> api_error;
|
||||
|
||||
public:
|
||||
void add(std::uint64_t handle, open_file_data ofd) override;
|
||||
|
||||
[[nodiscard]] auto can_close() const -> bool override;
|
||||
|
||||
auto close() -> bool override;
|
||||
|
||||
[[nodiscard]] auto get_api_error() const -> api_error;
|
||||
|
||||
[[nodiscard]] auto get_api_path() const -> std::string override;
|
||||
|
||||
[[nodiscard]] auto get_chunk_size() const -> std::size_t override {
|
||||
return chunk_size_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_file_size() const -> std::uint64_t override;
|
||||
|
||||
[[nodiscard]] auto get_filesystem_item() const -> filesystem_item override;
|
||||
|
||||
[[nodiscard]] auto get_handles() const -> std::vector<std::uint64_t> override;
|
||||
|
||||
[[nodiscard]] auto get_open_data()
|
||||
-> std::map<std::uint64_t, open_file_data> & override;
|
||||
|
||||
[[nodiscard]] auto get_open_data() const
|
||||
-> const std::map<std::uint64_t, open_file_data> & override;
|
||||
|
||||
[[nodiscard]] auto get_open_data(std::uint64_t handle)
|
||||
-> open_file_data & override;
|
||||
|
||||
[[nodiscard]] auto get_open_data(std::uint64_t handle) const
|
||||
-> const open_file_data & override;
|
||||
|
||||
[[nodiscard]] auto get_open_file_count() const -> std::size_t override;
|
||||
|
||||
[[nodiscard]] auto get_source_path() const -> std::string override {
|
||||
return fsi_.source_path;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto has_handle(std::uint64_t handle) const -> bool override {
|
||||
return open_data_.find(handle) != open_data_.end();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto is_directory() const -> bool override {
|
||||
return fsi_.directory;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto is_modified() const -> bool override;
|
||||
|
||||
void remove(std::uint64_t handle) override;
|
||||
|
||||
void set_api_path(const std::string &api_path) override;
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // REPERTORY_INCLUDE_FILE_MANAGER_OPEN_FILE_BASE_HPP_
|
@ -0,0 +1,132 @@
|
||||
/*
|
||||
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#ifndef REPERTORY_INCLUDE_FILE_MANAGER_RING_BUFFER_OPEN_FILE_HPP_
|
||||
#define REPERTORY_INCLUDE_FILE_MANAGER_RING_BUFFER_OPEN_FILE_HPP_
|
||||
|
||||
#include "file_manager/open_file_base.hpp"
|
||||
|
||||
#include "types/repertory.hpp"
|
||||
|
||||
namespace repertory {
|
||||
class i_provider;
|
||||
class i_upload_manager;
|
||||
|
||||
class ring_buffer_open_file final : public open_file_base {
|
||||
public:
|
||||
ring_buffer_open_file(std::string buffer_directory, std::uint64_t chunk_size,
|
||||
std::uint8_t chunk_timeout, filesystem_item fsi,
|
||||
i_provider &provider);
|
||||
|
||||
ring_buffer_open_file(std::string buffer_directory, std::uint64_t chunk_size,
|
||||
std::uint8_t chunk_timeout, filesystem_item fsi,
|
||||
i_provider &provider, std::size_t ring_size);
|
||||
|
||||
~ring_buffer_open_file() override;
|
||||
|
||||
public:
|
||||
ring_buffer_open_file() = delete;
|
||||
ring_buffer_open_file(const ring_buffer_open_file &) noexcept = delete;
|
||||
ring_buffer_open_file(ring_buffer_open_file &&) noexcept = delete;
|
||||
auto operator=(ring_buffer_open_file &&) noexcept
|
||||
-> ring_buffer_open_file & = delete;
|
||||
auto operator=(const ring_buffer_open_file &) noexcept
|
||||
-> ring_buffer_open_file & = delete;
|
||||
|
||||
private:
|
||||
boost::dynamic_bitset<> ring_state_;
|
||||
std::size_t total_chunks_;
|
||||
|
||||
private:
|
||||
std::unique_ptr<std::thread> chunk_forward_thread_;
|
||||
std::unique_ptr<std::thread> chunk_reverse_thread_;
|
||||
std::condition_variable chunk_notify_;
|
||||
mutable std::mutex chunk_mtx_;
|
||||
std::size_t current_chunk_{};
|
||||
std::size_t first_chunk_{};
|
||||
std::size_t last_chunk_;
|
||||
|
||||
private:
|
||||
auto download_chunk(std::size_t chunk) -> api_error;
|
||||
|
||||
void forward_reader_thread(std::size_t count);
|
||||
|
||||
void reverse_reader_thread(std::size_t count);
|
||||
|
||||
protected:
|
||||
auto is_download_complete() const -> bool override;
|
||||
|
||||
public:
|
||||
void forward(std::size_t count);
|
||||
|
||||
[[nodiscard]] auto get_current_chunk() const -> std::size_t {
|
||||
return current_chunk_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_first_chunk() const -> std::size_t {
|
||||
return first_chunk_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_last_chunk() const -> std::size_t {
|
||||
return last_chunk_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto get_read_state() const -> boost::dynamic_bitset<> override;
|
||||
|
||||
[[nodiscard]] auto get_read_state(std::size_t chunk) const -> bool override;
|
||||
|
||||
[[nodiscard]] auto get_total_chunks() const -> std::size_t {
|
||||
return total_chunks_;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto is_complete() const -> bool override { return true; }
|
||||
|
||||
auto is_write_supported() const -> bool override { return false; }
|
||||
|
||||
[[nodiscard]] auto native_operation(native_operation_callback callback)
|
||||
-> api_error override;
|
||||
|
||||
[[nodiscard]] auto native_operation(std::uint64_t, native_operation_callback)
|
||||
-> api_error override {
|
||||
return api_error::not_supported;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto read(std::size_t read_size, std::uint64_t read_offset,
|
||||
data_buffer &data) -> api_error override;
|
||||
|
||||
[[nodiscard]] auto resize(std::uint64_t) -> api_error override {
|
||||
return api_error::not_supported;
|
||||
}
|
||||
|
||||
void reverse(std::size_t count);
|
||||
|
||||
void set(std::size_t first_chunk, std::size_t current_chunk);
|
||||
|
||||
void set_api_path(const std::string &api_path) override;
|
||||
|
||||
[[nodiscard]] auto write(std::uint64_t, const data_buffer &, std::size_t &)
|
||||
-> api_error override {
|
||||
return api_error::not_supported;
|
||||
}
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // REPERTORY_INCLUDE_FILE_MANAGER_RING_BUFFER_OPEN_FILE_HPP_
|
@ -19,23 +19,57 @@
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#include "file_manager/file_manager.hpp"
|
||||
#ifndef REPERTORY_INCLUDE_FILE_MANAGER_UPLOAD_HPP_
|
||||
#define REPERTORY_INCLUDE_FILE_MANAGER_UPLOAD_HPP_
|
||||
|
||||
#include "types/repertory.hpp"
|
||||
|
||||
namespace repertory {
|
||||
void file_manager::open_file_base::io_item::action() {
|
||||
result_ = action_();
|
||||
class i_provider;
|
||||
|
||||
mutex_lock lock(mtx_);
|
||||
notify_.notify_all();
|
||||
}
|
||||
class upload final {
|
||||
public:
|
||||
upload(filesystem_item fsi, i_provider &provider);
|
||||
|
||||
auto file_manager::open_file_base::io_item::get_result() -> api_error {
|
||||
unique_mutex_lock lock(mtx_);
|
||||
if (result_.has_value()) {
|
||||
return result_.value();
|
||||
~upload();
|
||||
|
||||
public:
|
||||
upload() = delete;
|
||||
upload(const upload &) noexcept = delete;
|
||||
upload(upload &&) noexcept = delete;
|
||||
auto operator=(upload &&) noexcept -> upload & = delete;
|
||||
auto operator=(const upload &) noexcept -> upload & = delete;
|
||||
|
||||
private:
|
||||
filesystem_item fsi_;
|
||||
i_provider &provider_;
|
||||
|
||||
private:
|
||||
bool cancelled_{false};
|
||||
api_error error_{api_error::success};
|
||||
std::unique_ptr<std::thread> thread_;
|
||||
stop_type stop_requested_{false};
|
||||
|
||||
private:
|
||||
void upload_thread();
|
||||
|
||||
public:
|
||||
void cancel();
|
||||
|
||||
[[nodiscard]] auto get_api_error() const -> api_error { return error_; }
|
||||
|
||||
[[nodiscard]] auto get_api_path() const -> std::string {
|
||||
return fsi_.api_path;
|
||||
}
|
||||
|
||||
notify_.wait(lock);
|
||||
return result_.value_or(api_error::error);
|
||||
}
|
||||
[[nodiscard]] auto get_source_path() const -> std::string {
|
||||
return fsi_.source_path;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto is_cancelled() const -> bool { return cancelled_; }
|
||||
|
||||
void stop();
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
#endif // REPERTORY_INCLUDE_FILE_MANAGER_UPLOAD_HPP_
|
@ -23,6 +23,10 @@
|
||||
|
||||
#include "app_config.hpp"
|
||||
#include "file_manager/events.hpp"
|
||||
#include "file_manager/open_file.hpp"
|
||||
#include "file_manager/open_file_base.hpp"
|
||||
#include "file_manager/ring_buffer_open_file.hpp"
|
||||
#include "file_manager/upload.hpp"
|
||||
#include "providers/i_provider.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
#include "utils/common.hpp"
|
||||
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
Copyright <2018-2024> <scott.e.graves@protonmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#include "file_manager/file_manager.hpp"
|
||||
|
||||
namespace repertory {
|
||||
void file_manager::open_file_base::download::notify(const api_error &err) {
|
||||
complete_ = true;
|
||||
error_ = err;
|
||||
unique_mutex_lock lock(mtx_);
|
||||
notify_.notify_all();
|
||||
}
|
||||
|
||||
auto file_manager::open_file_base::download::wait() -> api_error {
|
||||
if (not complete_) {
|
||||
unique_mutex_lock lock(mtx_);
|
||||
if (not complete_) {
|
||||
notify_.wait(lock);
|
||||
}
|
||||
notify_.notify_all();
|
||||
}
|
||||
|
||||
return error_;
|
||||
}
|
||||
} // namespace repertory
|
@ -19,9 +19,10 @@
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#include "file_manager/file_manager.hpp"
|
||||
#include "file_manager/open_file.hpp"
|
||||
|
||||
#include "file_manager/events.hpp"
|
||||
#include "file_manager/i_upload_manager.hpp"
|
||||
#include "platform/platform.hpp"
|
||||
#include "providers/i_provider.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
@ -34,31 +35,32 @@
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
file_manager::open_file::open_file(std::uint64_t chunk_size,
|
||||
std::uint8_t chunk_timeout,
|
||||
open_file::open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi, i_provider &provider,
|
||||
i_upload_manager &mgr)
|
||||
: open_file(chunk_size, chunk_timeout, fsi, {}, provider, std::nullopt,
|
||||
mgr) {}
|
||||
|
||||
file_manager::open_file::open_file(
|
||||
std::uint64_t chunk_size, std::uint8_t chunk_timeout, filesystem_item fsi,
|
||||
std::map<std::uint64_t, open_file_data> open_data, i_provider &provider,
|
||||
i_upload_manager &mgr)
|
||||
open_file::open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi,
|
||||
std::map<std::uint64_t, open_file_data> open_data,
|
||||
i_provider &provider, i_upload_manager &mgr)
|
||||
: open_file(chunk_size, chunk_timeout, fsi, open_data, provider,
|
||||
std::nullopt, mgr) {}
|
||||
|
||||
file_manager::open_file::open_file(
|
||||
std::uint64_t chunk_size, std::uint8_t chunk_timeout, filesystem_item fsi,
|
||||
i_provider &provider, std::optional<boost::dynamic_bitset<>> read_state,
|
||||
open_file::open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi, i_provider &provider,
|
||||
std::optional<boost::dynamic_bitset<>> read_state,
|
||||
i_upload_manager &mgr)
|
||||
: open_file(chunk_size, chunk_timeout, fsi, {}, provider, read_state, mgr) {
|
||||
}
|
||||
|
||||
file_manager::open_file::open_file(
|
||||
std::uint64_t chunk_size, std::uint8_t chunk_timeout, filesystem_item fsi,
|
||||
std::map<std::uint64_t, open_file_data> open_data, i_provider &provider,
|
||||
std::optional<boost::dynamic_bitset<>> read_state, i_upload_manager &mgr)
|
||||
open_file::open_file(std::uint64_t chunk_size, std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi,
|
||||
std::map<std::uint64_t, open_file_data> open_data,
|
||||
i_provider &provider,
|
||||
std::optional<boost::dynamic_bitset<>> read_state,
|
||||
i_upload_manager &mgr)
|
||||
: open_file_base(chunk_size, chunk_timeout, fsi, open_data, provider),
|
||||
mgr_(mgr) {
|
||||
if (fsi_.directory && read_state.has_value()) {
|
||||
@ -93,10 +95,9 @@ file_manager::open_file::open_file(
|
||||
}
|
||||
}
|
||||
|
||||
file_manager::open_file::~open_file() { close(); }
|
||||
open_file::~open_file() { close(); }
|
||||
|
||||
void file_manager::open_file::download_chunk(std::size_t chunk,
|
||||
bool skip_active,
|
||||
void open_file::download_chunk(std::size_t chunk, bool skip_active,
|
||||
bool should_reset) {
|
||||
if (should_reset) {
|
||||
reset_timeout();
|
||||
@ -206,8 +207,8 @@ void file_manager::open_file::download_chunk(std::size_t chunk,
|
||||
}
|
||||
}
|
||||
|
||||
void file_manager::open_file::download_range(
|
||||
std::size_t start_chunk_index, std::size_t end_chunk_index_inclusive,
|
||||
void open_file::download_range(std::size_t start_chunk_index,
|
||||
std::size_t end_chunk_index_inclusive,
|
||||
bool should_reset) {
|
||||
for (std::size_t chunk = start_chunk_index;
|
||||
chunk <= end_chunk_index_inclusive; chunk++) {
|
||||
@ -218,23 +219,22 @@ void file_manager::open_file::download_range(
|
||||
}
|
||||
}
|
||||
|
||||
auto file_manager::open_file::get_read_state() const
|
||||
-> boost::dynamic_bitset<> {
|
||||
auto open_file::get_read_state() const -> boost::dynamic_bitset<> {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
return read_state_;
|
||||
}
|
||||
|
||||
auto file_manager::open_file::get_read_state(std::size_t chunk) const -> bool {
|
||||
auto open_file::get_read_state(std::size_t chunk) const -> bool {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
return read_state_[chunk];
|
||||
}
|
||||
|
||||
auto file_manager::open_file::is_complete() const -> bool {
|
||||
auto open_file::is_complete() const -> bool {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
return read_state_.all();
|
||||
}
|
||||
|
||||
auto file_manager::open_file::native_operation(
|
||||
auto open_file::native_operation(
|
||||
i_open_file::native_operation_callback callback) -> api_error {
|
||||
unique_recur_mutex_lock file_lock(file_mtx_);
|
||||
if (stop_requested_) {
|
||||
@ -245,7 +245,7 @@ auto file_manager::open_file::native_operation(
|
||||
return do_io([&]() -> api_error { return callback(nf_->get_handle()); });
|
||||
}
|
||||
|
||||
auto file_manager::open_file::native_operation(
|
||||
auto open_file::native_operation(
|
||||
std::uint64_t new_file_size,
|
||||
i_open_file::native_operation_callback callback) -> api_error {
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
@ -336,9 +336,8 @@ auto file_manager::open_file::native_operation(
|
||||
return res;
|
||||
}
|
||||
|
||||
auto file_manager::open_file::read(std::size_t read_size,
|
||||
std::uint64_t read_offset, data_buffer &data)
|
||||
-> api_error {
|
||||
auto open_file::read(std::size_t read_size, std::uint64_t read_offset,
|
||||
data_buffer &data) -> api_error {
|
||||
if (fsi_.directory) {
|
||||
return api_error::invalid_operation;
|
||||
}
|
||||
@ -389,7 +388,7 @@ auto file_manager::open_file::read(std::size_t read_size,
|
||||
: get_api_error();
|
||||
}
|
||||
|
||||
void file_manager::open_file::remove(std::uint64_t handle) {
|
||||
void open_file::remove(std::uint64_t handle) {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
open_file_base::remove(handle);
|
||||
if (modified_ && read_state_.all() &&
|
||||
@ -403,7 +402,7 @@ void file_manager::open_file::remove(std::uint64_t handle) {
|
||||
}
|
||||
}
|
||||
|
||||
auto file_manager::open_file::resize(std::uint64_t new_file_size) -> api_error {
|
||||
auto open_file::resize(std::uint64_t new_file_size) -> api_error {
|
||||
if (fsi_.directory) {
|
||||
return api_error::invalid_operation;
|
||||
}
|
||||
@ -415,7 +414,7 @@ auto file_manager::open_file::resize(std::uint64_t new_file_size) -> api_error {
|
||||
});
|
||||
}
|
||||
|
||||
auto file_manager::open_file::close() -> bool {
|
||||
auto open_file::close() -> bool {
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
|
||||
if (not fsi_.directory && not stop_requested_) {
|
||||
@ -479,7 +478,7 @@ auto file_manager::open_file::close() -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
void file_manager::open_file::set_modified() {
|
||||
void open_file::set_modified() {
|
||||
if (not modified_) {
|
||||
modified_ = true;
|
||||
mgr_.store_resume(*this);
|
||||
@ -491,7 +490,7 @@ void file_manager::open_file::set_modified() {
|
||||
}
|
||||
}
|
||||
|
||||
void file_manager::open_file::update_background_reader(std::size_t read_chunk) {
|
||||
void open_file::update_background_reader(std::size_t read_chunk) {
|
||||
recur_mutex_lock reader_lock(file_mtx_);
|
||||
read_chunk_index_ = read_chunk;
|
||||
|
||||
@ -526,8 +525,7 @@ void file_manager::open_file::update_background_reader(std::size_t read_chunk) {
|
||||
}
|
||||
}
|
||||
|
||||
auto file_manager::open_file::write(std::uint64_t write_offset,
|
||||
const data_buffer &data,
|
||||
auto open_file::write(std::uint64_t write_offset, const data_buffer &data,
|
||||
std::size_t &bytes_written) -> api_error {
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
|
@ -19,19 +19,55 @@
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#include "file_manager/file_manager.hpp"
|
||||
#include "file_manager/open_file_base.hpp"
|
||||
|
||||
#include "file_manager/events.hpp"
|
||||
#include "providers/i_provider.hpp"
|
||||
#include "utils/path.hpp"
|
||||
|
||||
namespace repertory {
|
||||
file_manager::open_file_base::open_file_base(std::uint64_t chunk_size,
|
||||
std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi,
|
||||
void open_file_base::download::notify(const api_error &err) {
|
||||
complete_ = true;
|
||||
error_ = err;
|
||||
unique_mutex_lock lock(mtx_);
|
||||
notify_.notify_all();
|
||||
}
|
||||
|
||||
auto open_file_base::download::wait() -> api_error {
|
||||
if (not complete_) {
|
||||
unique_mutex_lock lock(mtx_);
|
||||
if (not complete_) {
|
||||
notify_.wait(lock);
|
||||
}
|
||||
notify_.notify_all();
|
||||
}
|
||||
|
||||
return error_;
|
||||
}
|
||||
|
||||
void open_file_base::io_item::action() {
|
||||
result_ = action_();
|
||||
|
||||
mutex_lock lock(mtx_);
|
||||
notify_.notify_all();
|
||||
}
|
||||
|
||||
auto open_file_base::io_item::get_result() -> api_error {
|
||||
unique_mutex_lock lock(mtx_);
|
||||
if (result_.has_value()) {
|
||||
return result_.value();
|
||||
}
|
||||
|
||||
notify_.wait(lock);
|
||||
return result_.value_or(api_error::error);
|
||||
}
|
||||
|
||||
open_file_base::open_file_base(std::uint64_t chunk_size,
|
||||
std::uint8_t chunk_timeout, filesystem_item fsi,
|
||||
i_provider &provider)
|
||||
: open_file_base(chunk_size, chunk_timeout, fsi, {}, provider) {}
|
||||
|
||||
file_manager::open_file_base::open_file_base(
|
||||
open_file_base::open_file_base(
|
||||
std::uint64_t chunk_size, std::uint8_t chunk_timeout, filesystem_item fsi,
|
||||
std::map<std::uint64_t, open_file_data> open_data, i_provider &provider)
|
||||
: chunk_size_(chunk_size),
|
||||
@ -48,8 +84,7 @@ file_manager::open_file_base::open_file_base(
|
||||
}
|
||||
}
|
||||
|
||||
void file_manager::open_file_base::add(std::uint64_t handle,
|
||||
open_file_data ofd) {
|
||||
void open_file_base::add(std::uint64_t handle, open_file_data ofd) {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
open_data_[handle] = ofd;
|
||||
if (open_data_.size() == 1U) {
|
||||
@ -61,7 +96,7 @@ void file_manager::open_file_base::add(std::uint64_t handle,
|
||||
fsi_.api_path, handle, fsi_.source_path, fsi_.directory);
|
||||
}
|
||||
|
||||
auto file_manager::open_file_base::can_close() const -> bool {
|
||||
auto open_file_base::can_close() const -> bool {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
if (fsi_.directory) {
|
||||
return true;
|
||||
@ -93,8 +128,7 @@ auto file_manager::open_file_base::can_close() const -> bool {
|
||||
return (duration.count() >= chunk_timeout_);
|
||||
}
|
||||
|
||||
auto file_manager::open_file_base::do_io(std::function<api_error()> action)
|
||||
-> api_error {
|
||||
auto open_file_base::do_io(std::function<api_error()> action) -> api_error {
|
||||
unique_mutex_lock io_lock(io_thread_mtx_);
|
||||
auto item = std::make_shared<io_item>(action);
|
||||
io_thread_queue_.emplace_back(item);
|
||||
@ -104,7 +138,7 @@ auto file_manager::open_file_base::do_io(std::function<api_error()> action)
|
||||
return item->get_result();
|
||||
}
|
||||
|
||||
void file_manager::open_file_base::file_io_thread() {
|
||||
void open_file_base::file_io_thread() {
|
||||
unique_mutex_lock io_lock(io_thread_mtx_);
|
||||
io_thread_notify_.notify_all();
|
||||
io_lock.unlock();
|
||||
@ -137,29 +171,27 @@ void file_manager::open_file_base::file_io_thread() {
|
||||
process_queue();
|
||||
}
|
||||
|
||||
auto file_manager::open_file_base::get_api_error() const -> api_error {
|
||||
auto open_file_base::get_api_error() const -> api_error {
|
||||
mutex_lock error_lock(error_mtx_);
|
||||
return error_;
|
||||
}
|
||||
|
||||
auto file_manager::open_file_base::get_api_path() const -> std::string {
|
||||
auto open_file_base::get_api_path() const -> std::string {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
return fsi_.api_path;
|
||||
}
|
||||
|
||||
auto file_manager::open_file_base::get_file_size() const -> std::uint64_t {
|
||||
auto open_file_base::get_file_size() const -> std::uint64_t {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
return fsi_.size;
|
||||
}
|
||||
|
||||
auto file_manager::open_file_base::get_filesystem_item() const
|
||||
-> filesystem_item {
|
||||
auto open_file_base::get_filesystem_item() const -> filesystem_item {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
return fsi_;
|
||||
}
|
||||
|
||||
auto file_manager::open_file_base::get_handles() const
|
||||
-> std::vector<std::uint64_t> {
|
||||
auto open_file_base::get_handles() const -> std::vector<std::uint64_t> {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
std::vector<std::uint64_t> ret;
|
||||
for (auto &&item : open_data_) {
|
||||
@ -169,41 +201,40 @@ auto file_manager::open_file_base::get_handles() const
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto file_manager::open_file_base::get_open_data()
|
||||
auto open_file_base::get_open_data()
|
||||
-> std::map<std::uint64_t, open_file_data> & {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
return open_data_;
|
||||
}
|
||||
|
||||
auto file_manager::open_file_base::get_open_data() const
|
||||
auto open_file_base::get_open_data() const
|
||||
-> const std::map<std::uint64_t, open_file_data> & {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
return open_data_;
|
||||
}
|
||||
|
||||
auto file_manager::open_file_base::get_open_data(std::uint64_t handle)
|
||||
-> open_file_data & {
|
||||
auto open_file_base::get_open_data(std::uint64_t handle) -> open_file_data & {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
return open_data_.at(handle);
|
||||
}
|
||||
|
||||
auto file_manager::open_file_base::get_open_data(std::uint64_t handle) const
|
||||
auto open_file_base::get_open_data(std::uint64_t handle) const
|
||||
-> const open_file_data & {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
return open_data_.at(handle);
|
||||
}
|
||||
|
||||
auto file_manager::open_file_base::get_open_file_count() const -> std::size_t {
|
||||
auto open_file_base::get_open_file_count() const -> std::size_t {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
return open_data_.size();
|
||||
}
|
||||
|
||||
auto file_manager::open_file_base::is_modified() const -> bool {
|
||||
auto open_file_base::is_modified() const -> bool {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
return modified_;
|
||||
}
|
||||
|
||||
void file_manager::open_file_base::remove(std::uint64_t handle) {
|
||||
void open_file_base::remove(std::uint64_t handle) {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
open_data_.erase(handle);
|
||||
event_system::instance().raise<filesystem_item_handle_closed>(
|
||||
@ -214,12 +245,11 @@ void file_manager::open_file_base::remove(std::uint64_t handle) {
|
||||
}
|
||||
}
|
||||
|
||||
void file_manager::open_file_base::reset_timeout() {
|
||||
void open_file_base::reset_timeout() {
|
||||
last_access_ = std::chrono::system_clock::now();
|
||||
}
|
||||
|
||||
auto file_manager::open_file_base::set_api_error(const api_error &err)
|
||||
-> api_error {
|
||||
auto open_file_base::set_api_error(const api_error &err) -> api_error {
|
||||
mutex_lock error_lock(error_mtx_);
|
||||
if (error_ != err) {
|
||||
return ((error_ = (error_ == api_error::success ||
|
||||
@ -232,13 +262,13 @@ auto file_manager::open_file_base::set_api_error(const api_error &err)
|
||||
return error_;
|
||||
}
|
||||
|
||||
void file_manager::open_file_base::set_api_path(const std::string &api_path) {
|
||||
void open_file_base::set_api_path(const std::string &api_path) {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
fsi_.api_path = api_path;
|
||||
fsi_.api_parent = utils::path::get_parent_api_path(api_path);
|
||||
}
|
||||
|
||||
auto file_manager::open_file_base::close() -> bool {
|
||||
auto open_file_base::close() -> bool {
|
||||
unique_mutex_lock io_lock(io_thread_mtx_);
|
||||
if (not fsi_.directory && not io_stop_requested_) {
|
||||
io_stop_requested_ = true;
|
@ -19,10 +19,11 @@
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#include "file_manager/file_manager.hpp"
|
||||
#include "file_manager/ring_buffer_open_file.hpp"
|
||||
|
||||
#include "app_config.hpp"
|
||||
#include "file_manager/events.hpp"
|
||||
#include "file_manager/open_file_base.hpp"
|
||||
#include "platform/platform.hpp"
|
||||
#include "providers/i_provider.hpp"
|
||||
#include "types/repertory.hpp"
|
||||
@ -33,16 +34,20 @@
|
||||
#include "utils/utils.hpp"
|
||||
|
||||
namespace repertory {
|
||||
file_manager::ring_buffer_open_file::ring_buffer_open_file(
|
||||
std::string buffer_directory, std::uint64_t chunk_size,
|
||||
std::uint8_t chunk_timeout, filesystem_item fsi, i_provider &provider)
|
||||
ring_buffer_open_file::ring_buffer_open_file(std::string buffer_directory,
|
||||
std::uint64_t chunk_size,
|
||||
std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi,
|
||||
i_provider &provider)
|
||||
: ring_buffer_open_file(std::move(buffer_directory), chunk_size,
|
||||
chunk_timeout, std::move(fsi), provider,
|
||||
(1024ULL * 1024ULL * 1024ULL) / chunk_size) {}
|
||||
|
||||
file_manager::ring_buffer_open_file::ring_buffer_open_file(
|
||||
std::string buffer_directory, std::uint64_t chunk_size,
|
||||
std::uint8_t chunk_timeout, filesystem_item fsi, i_provider &provider,
|
||||
ring_buffer_open_file::ring_buffer_open_file(std::string buffer_directory,
|
||||
std::uint64_t chunk_size,
|
||||
std::uint8_t chunk_timeout,
|
||||
filesystem_item fsi,
|
||||
i_provider &provider,
|
||||
std::size_t ring_size)
|
||||
: open_file_base(chunk_size, chunk_timeout, fsi, provider),
|
||||
ring_state_(ring_size),
|
||||
@ -85,7 +90,7 @@ file_manager::ring_buffer_open_file::ring_buffer_open_file(
|
||||
}
|
||||
}
|
||||
|
||||
file_manager::ring_buffer_open_file::~ring_buffer_open_file() {
|
||||
ring_buffer_open_file::~ring_buffer_open_file() {
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
|
||||
close();
|
||||
@ -98,8 +103,7 @@ file_manager::ring_buffer_open_file::~ring_buffer_open_file() {
|
||||
}
|
||||
}
|
||||
|
||||
auto file_manager::file_manager::ring_buffer_open_file::download_chunk(
|
||||
std::size_t chunk) -> api_error {
|
||||
auto r::ring_buffer_open_file::download_chunk(std::size_t chunk) -> api_error {
|
||||
unique_mutex_lock chunk_lock(chunk_mtx_);
|
||||
if (active_downloads_.find(chunk) != active_downloads_.end()) {
|
||||
auto active_download = active_downloads_.at(chunk);
|
||||
@ -149,7 +153,7 @@ auto file_manager::file_manager::ring_buffer_open_file::download_chunk(
|
||||
return api_error::success;
|
||||
}
|
||||
|
||||
void file_manager::ring_buffer_open_file::forward(std::size_t count) {
|
||||
void ring_buffer_open_file::forward(std::size_t count) {
|
||||
mutex_lock chunk_lock(chunk_mtx_);
|
||||
if ((current_chunk_ + count) > (total_chunks_ - 1U)) {
|
||||
count = (total_chunks_ - 1U) - current_chunk_;
|
||||
@ -179,29 +183,27 @@ void file_manager::ring_buffer_open_file::forward(std::size_t count) {
|
||||
chunk_notify_.notify_all();
|
||||
}
|
||||
|
||||
auto file_manager::ring_buffer_open_file::get_read_state() const
|
||||
-> boost::dynamic_bitset<> {
|
||||
auto ring_buffer_open_file::get_read_state() const -> boost::dynamic_bitset<> {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
auto read_state = ring_state_;
|
||||
return read_state.flip();
|
||||
}
|
||||
|
||||
auto file_manager::ring_buffer_open_file::get_read_state(
|
||||
std::size_t chunk) const -> bool {
|
||||
auto ring_buffer_open_file::get_read_state(std::size_t chunk) const -> bool {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
return not ring_state_[chunk % ring_state_.size()];
|
||||
}
|
||||
|
||||
auto file_manager::ring_buffer_open_file::is_download_complete() const -> bool {
|
||||
auto ring_buffer_open_file::is_download_complete() const -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto file_manager::ring_buffer_open_file::native_operation(
|
||||
auto ring_buffer_open_file::native_operation(
|
||||
i_open_file::native_operation_callback callback) -> api_error {
|
||||
return do_io([&]() -> api_error { return callback(nf_->get_handle()); });
|
||||
}
|
||||
|
||||
void file_manager::ring_buffer_open_file::reverse(std::size_t count) {
|
||||
void ring_buffer_open_file::reverse(std::size_t count) {
|
||||
mutex_lock chunk_lock(chunk_mtx_);
|
||||
if (current_chunk_ < count) {
|
||||
count = current_chunk_;
|
||||
@ -231,9 +233,9 @@ void file_manager::ring_buffer_open_file::reverse(std::size_t count) {
|
||||
chunk_notify_.notify_all();
|
||||
}
|
||||
|
||||
auto file_manager::ring_buffer_open_file::read(std::size_t read_size,
|
||||
std::uint64_t read_offset,
|
||||
data_buffer &data) -> api_error {
|
||||
auto ring_buffer_open_file::read(std::size_t read_size,
|
||||
std::uint64_t read_offset, data_buffer &data)
|
||||
-> api_error {
|
||||
if (fsi_.directory) {
|
||||
return api_error::invalid_operation;
|
||||
}
|
||||
@ -290,7 +292,7 @@ auto file_manager::ring_buffer_open_file::read(std::size_t read_size,
|
||||
return res;
|
||||
}
|
||||
|
||||
void file_manager::ring_buffer_open_file::set(std::size_t first_chunk,
|
||||
void ring_buffer_open_file::set(std::size_t first_chunk,
|
||||
std::size_t current_chunk) {
|
||||
mutex_lock chunk_lock(chunk_mtx_);
|
||||
if (first_chunk >= total_chunks_) {
|
||||
@ -313,8 +315,7 @@ void file_manager::ring_buffer_open_file::set(std::size_t first_chunk,
|
||||
chunk_notify_.notify_all();
|
||||
}
|
||||
|
||||
void file_manager::ring_buffer_open_file::set_api_path(
|
||||
const std::string &api_path) {
|
||||
void ring_buffer_open_file::set_api_path(const std::string &api_path) {
|
||||
mutex_lock chunk_lock(chunk_mtx_);
|
||||
open_file_base::set_api_path(api_path);
|
||||
chunk_notify_.notify_all();
|
@ -19,7 +19,7 @@
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
#include "file_manager/file_manager.hpp"
|
||||
#include "file_manager/upload.hpp"
|
||||
|
||||
#include "platform/platform.hpp"
|
||||
#include "providers/i_provider.hpp"
|
@ -157,8 +157,8 @@ template <typename ctx_t, typename op_t> struct db_where_t final {
|
||||
|
||||
using action_t = std::variant<db_comp_data_t, n_t, db_where_t>;
|
||||
|
||||
[[nodiscard]] static auto dump(std::int32_t &idx,
|
||||
auto &&actions) -> std::string {
|
||||
[[nodiscard]] static auto dump(std::int32_t &idx, auto &&actions)
|
||||
-> std::string {
|
||||
std::stringstream stream;
|
||||
|
||||
for (auto &&action : actions) {
|
||||
|
@ -27,13 +27,12 @@ std::atomic<const i_exception_handler *> exception_handler{
|
||||
|
||||
auto create_error_message(std::vector<std::string_view> items) -> std::string {
|
||||
std::stringstream stream{};
|
||||
stream << function_name;
|
||||
for (std::size_t idx = 0U; idx < items.size(); ++idx) {
|
||||
if (idx > 0) {
|
||||
stream << '|';
|
||||
}
|
||||
|
||||
stream << item;
|
||||
stream << items.at(idx);
|
||||
}
|
||||
|
||||
return stream.str();
|
||||
|
@ -397,6 +397,8 @@ auto file::sha256() -> std::optional<std::string> {
|
||||
#endif // defined(PROJECT_ENABLE_LIBSODIUM)
|
||||
|
||||
auto file::remove() -> bool {
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
|
||||
close();
|
||||
|
||||
return utils::retry_action([this]() -> bool {
|
||||
|
Loading…
x
Reference in New Issue
Block a user