20 Commits

Author SHA1 Message Date
2a80d4053c troubleshoot deadlock
All checks were successful
BlockStorage/repertory/pipeline/head This commit looks good
2024-12-23 12:50:33 -06:00
ac3e7eef61 Complete ring buffer and direct download support #26 2024-12-23 10:06:15 -06:00
63c1b83f18 Complete ring buffer and direct download support #26 2024-12-23 10:04:30 -06:00
a8f16ab89d fix progress 2024-12-23 09:53:46 -06:00
8c412a6cff Complete ring buffer and direct download support #26 2024-12-23 09:42:41 -06:00
29d83fc5e8 Complete ring buffer and direct download support #26 2024-12-23 09:31:36 -06:00
6fe0088c1b Complete ring buffer and direct download support #26 2024-12-23 09:29:43 -06:00
b3f7a9b659 Complete ring buffer and direct download support #26 2024-12-23 09:28:01 -06:00
2d5508eb7c Complete ring buffer and direct download support #26 2024-12-23 09:27:17 -06:00
1a84e507fc Complete ring buffer and direct download support #26 2024-12-23 08:54:01 -06:00
4f419be42d Complete ring buffer and direct download support #26 2024-12-23 08:51:49 -06:00
539d7e8402 Complete ring buffer and direct download support #26 2024-12-23 08:50:45 -06:00
ad22233308 Complete ring buffer and direct download support #26 2024-12-23 08:46:49 -06:00
f344665ddc Complete ring buffer and direct download support #26 2024-12-23 08:43:21 -06:00
8ff90ae769 Complete ring buffer and direct download support #26 2024-12-23 08:35:04 -06:00
2fd0ff8a93 Complete ring buffer and direct download support #26 2024-12-23 08:28:41 -06:00
3c659e57ec Complete ring buffer and direct download support #26 2024-12-23 08:27:37 -06:00
1c2d2cd13c Complete ring buffer and direct download support #26 2024-12-23 08:27:11 -06:00
ce1676f3d3 Complete ring buffer and direct download support #26 2024-12-23 07:53:42 -06:00
75a4676eac ring buffer background reader 2024-12-23 07:46:25 -06:00
11 changed files with 321 additions and 205 deletions

View File

@ -42,10 +42,11 @@ public:
direct_open_file(const direct_open_file &) noexcept = delete; direct_open_file(const direct_open_file &) noexcept = delete;
direct_open_file(direct_open_file &&) noexcept = delete; direct_open_file(direct_open_file &&) noexcept = delete;
auto operator=(direct_open_file &&) noexcept -> direct_open_file & = delete; auto operator=(direct_open_file &&) noexcept -> direct_open_file & = delete;
auto auto operator=(const direct_open_file &) noexcept
operator=(const direct_open_file &) noexcept -> direct_open_file & = delete; -> direct_open_file & = delete;
private: private:
std::atomic<std::uint64_t> last_progress_{0U};
std::size_t total_chunks_; std::size_t total_chunks_;
stop_type stop_requested_{false}; stop_type stop_requested_{false};
@ -63,13 +64,13 @@ public:
return false; return false;
} }
[[nodiscard]] auto [[nodiscard]] auto get_read_state() const
get_read_state() const -> boost::dynamic_bitset<> override { -> boost::dynamic_bitset<> override {
return {}; return {};
} }
[[nodiscard]] auto [[nodiscard]] auto get_read_state(std::size_t /* chunk */) const
get_read_state(std::size_t /* chunk */) const -> bool override { -> bool override {
return false; return false;
} }
@ -95,8 +96,8 @@ public:
return api_error::not_supported; return api_error::not_supported;
} }
[[nodiscard]] auto write(std::uint64_t, const data_buffer &, [[nodiscard]] auto write(std::uint64_t, const data_buffer &, std::size_t &)
std::size_t &) -> api_error override { -> api_error override {
return api_error::not_supported; return api_error::not_supported;
} }
}; };

View File

@ -42,8 +42,8 @@ public:
ring_buffer_open_file() = delete; ring_buffer_open_file() = delete;
ring_buffer_open_file(const ring_buffer_open_file &) noexcept = delete; ring_buffer_open_file(const ring_buffer_open_file &) noexcept = delete;
ring_buffer_open_file(ring_buffer_open_file &&) noexcept = delete; ring_buffer_open_file(ring_buffer_open_file &&) noexcept = delete;
auto operator=(ring_buffer_open_file &&) noexcept -> ring_buffer_open_file & = auto operator=(ring_buffer_open_file &&) noexcept
delete; -> ring_buffer_open_file & = delete;
auto operator=(const ring_buffer_open_file &) noexcept auto operator=(const ring_buffer_open_file &) noexcept
-> ring_buffer_open_file & = delete; -> ring_buffer_open_file & = delete;
@ -57,6 +57,7 @@ private:
std::condition_variable chunk_notify_; std::condition_variable chunk_notify_;
mutable std::mutex chunk_mtx_; mutable std::mutex chunk_mtx_;
std::mutex read_mtx_; std::mutex read_mtx_;
std::unique_ptr<std::thread> reader_thread_;
std::size_t ring_begin_{}; std::size_t ring_begin_{};
std::size_t ring_end_{}; std::size_t ring_end_{};
std::size_t ring_pos_{}; std::size_t ring_pos_{};
@ -64,11 +65,9 @@ private:
stop_type stop_requested_{false}; stop_type stop_requested_{false};
private: private:
auto download_chunk(std::size_t chunk) -> api_error; auto download_chunk(std::size_t chunk, bool skip_active) -> api_error;
void forward_reader_thread(std::size_t count); void background_reader_thread();
void reverse_reader_thread(std::size_t count);
protected: protected:
[[nodiscard]] auto is_download_complete() const -> bool override { [[nodiscard]] auto is_download_complete() const -> bool override {
@ -108,8 +107,8 @@ public:
return false; return false;
} }
[[nodiscard]] auto [[nodiscard]] auto native_operation(native_operation_callback callback)
native_operation(native_operation_callback callback) -> api_error override; -> api_error override;
[[nodiscard]] auto native_operation(std::uint64_t, native_operation_callback) [[nodiscard]] auto native_operation(std::uint64_t, native_operation_callback)
-> api_error override { -> api_error override {
@ -129,8 +128,8 @@ public:
void set_api_path(const std::string &api_path) override; void set_api_path(const std::string &api_path) override;
[[nodiscard]] auto write(std::uint64_t, const data_buffer &, [[nodiscard]] auto write(std::uint64_t, const data_buffer &, std::size_t &)
std::size_t &) -> api_error override { -> api_error override {
return api_error::not_supported; return api_error::not_supported;
} }
}; };

View File

@ -194,6 +194,7 @@ enum class api_error {
invalid_handle, invalid_handle,
invalid_operation, invalid_operation,
invalid_ring_buffer_multiple, invalid_ring_buffer_multiple,
invalid_ring_buffer_position,
invalid_ring_buffer_size, invalid_ring_buffer_size,
invalid_version, invalid_version,
item_exists, item_exists,
@ -215,31 +216,33 @@ enum class api_error {
[[nodiscard]] auto api_error_from_string(std::string_view str) -> api_error; [[nodiscard]] auto api_error_from_string(std::string_view str) -> api_error;
[[nodiscard]] auto [[nodiscard]] auto api_error_to_string(const api_error &error)
api_error_to_string(const api_error &error) -> const std::string &; -> const std::string &;
enum class database_type { enum class database_type {
rocksdb, rocksdb,
sqlite, sqlite,
}; };
[[nodiscard]] auto database_type_from_string(
std::string type,
database_type default_type = database_type::rocksdb) -> database_type;
[[nodiscard]] auto [[nodiscard]] auto
database_type_to_string(const database_type &type) -> std::string; database_type_from_string(std::string type,
database_type default_type = database_type::rocksdb)
-> database_type;
[[nodiscard]] auto database_type_to_string(const database_type &type)
-> std::string;
enum class download_type { enum class download_type {
direct, direct,
fallback, fallback,
ring_buffer, ring_buffer,
}; };
[[nodiscard]] auto download_type_from_string(
std::string type,
download_type default_type = download_type::fallback) -> download_type;
[[nodiscard]] auto [[nodiscard]] auto
download_type_to_string(const download_type &type) -> std::string; download_type_from_string(std::string type,
download_type default_type = download_type::fallback)
-> download_type;
[[nodiscard]] auto download_type_to_string(const download_type &type)
-> std::string;
enum class exit_code : std::int32_t { enum class exit_code : std::int32_t {
success = 0, success = 0,

View File

@ -21,10 +21,13 @@
*/ */
#include "file_manager/direct_open_file.hpp" #include "file_manager/direct_open_file.hpp"
#include "events/event_system.hpp"
#include "file_manager/events.hpp"
#include "file_manager/open_file_base.hpp" #include "file_manager/open_file_base.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/time.hpp"
namespace repertory { namespace repertory {
direct_open_file::direct_open_file(std::uint64_t chunk_size, direct_open_file::direct_open_file(std::uint64_t chunk_size,
@ -32,13 +35,20 @@ direct_open_file::direct_open_file(std::uint64_t chunk_size,
filesystem_item fsi, i_provider &provider) filesystem_item fsi, i_provider &provider)
: open_file_base(chunk_size, chunk_timeout, fsi, provider, true), : open_file_base(chunk_size, chunk_timeout, fsi, provider, true),
total_chunks_(static_cast<std::size_t>( total_chunks_(static_cast<std::size_t>(
utils::divide_with_ceiling(fsi.size, chunk_size))) {} utils::divide_with_ceiling(fsi.size, chunk_size))) {
event_system::instance().raise<download_begin>(fsi_.api_path, "");
}
direct_open_file::~direct_open_file() { close(); } direct_open_file::~direct_open_file() { close(); }
auto direct_open_file::close() -> bool { auto direct_open_file::close() -> bool {
stop_requested_ = true; stop_requested_ = true;
return open_file_base::close(); last_progress_ = 0U;
auto ret = open_file_base::close();
event_system::instance().raise<download_end>(fsi_.api_path, "",
api_error::download_stopped);
return ret;
} }
auto direct_open_file::read(std::size_t read_size, std::uint64_t read_offset, auto direct_open_file::read(std::size_t read_size, std::uint64_t read_offset,
@ -56,7 +66,20 @@ auto direct_open_file::read(std::size_t read_size, std::uint64_t read_offset,
auto res = provider_.read_file_bytes(fsi_.api_path, read_size, read_offset, auto res = provider_.read_file_bytes(fsi_.api_path, read_size, read_offset,
data, stop_requested_); data, stop_requested_);
if (res != api_error::success) {
return res;
}
reset_timeout(); reset_timeout();
if ((utils::time::get_time_now() - last_progress_.load()) >
(2U * utils::time::NANOS_PER_SECOND)) {
last_progress_ = utils::time::get_time_now();
auto progress = (static_cast<double>(read_offset + read_size) /
static_cast<double>(fsi_.size)) *
100.0;
event_system::instance().raise<download_progress>(fsi_.api_path, "",
progress);
}
return res; return res;
} }

View File

@ -137,17 +137,21 @@ auto file_manager::create(const std::string &api_path, api_meta_map &meta,
auto file_manager::evict_file(const std::string &api_path) -> bool { auto file_manager::evict_file(const std::string &api_path) -> bool {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
fmt::println("try evict|{}", api_path);
if (provider_.is_read_only()) { if (provider_.is_read_only()) {
return false; return false;
} }
recur_mutex_lock open_lock(open_file_mtx_); unique_recur_mutex_lock open_lock(open_file_mtx_);
fmt::println("try evict locked|{}", api_path);
if (is_processing(api_path)) { if (is_processing(api_path)) {
fmt::println("proccessing|{}", api_path);
return false; return false;
} }
if (get_open_file_count(api_path) != 0U) { if (get_open_file_count(api_path) != 0U) {
fmt::println("open count|{}", api_path);
return false; return false;
} }
@ -174,7 +178,14 @@ auto file_manager::evict_file(const std::string &api_path) -> bool {
return false; return false;
} }
std::shared_ptr<i_closeable_open_file> closeable_file;
if (open_file_lookup_.contains(api_path)) {
closeable_file = open_file_lookup_.at(api_path);
}
open_file_lookup_.erase(api_path); open_file_lookup_.erase(api_path);
open_lock.unlock();
closeable_file.reset();
auto file = utils::file::file{source_path}; auto file = utils::file::file{source_path};
auto file_size = file.size().value_or(0U); auto file_size = file.size().value_or(0U);
@ -372,10 +383,11 @@ auto file_manager::open(const std::string &api_path, bool directory,
return open(api_path, directory, ofd, handle, file, nullptr); return open(api_path, directory, ofd, handle, file, nullptr);
} }
auto file_manager::open( auto file_manager::open(const std::string &api_path, bool directory,
const std::string &api_path, bool directory, const open_file_data &ofd, const open_file_data &ofd, std::uint64_t &handle,
std::uint64_t &handle, std::shared_ptr<i_open_file> &file, std::shared_ptr<i_open_file> &file,
std::shared_ptr<i_closeable_open_file> closeable_file) -> api_error { std::shared_ptr<i_closeable_open_file> closeable_file)
-> api_error {
REPERTORY_USES_FUNCTION_NAME(); REPERTORY_USES_FUNCTION_NAME();
const auto create_and_add_handle = const auto create_and_add_handle =
@ -427,7 +439,7 @@ auto file_manager::open(
auto ring_size{ring_buffer_file_size / chunk_size}; auto ring_size{ring_buffer_file_size / chunk_size};
const auto get_download_type = [&](download_type type) -> download_type { const auto get_download_type = [&](download_type type) -> download_type {
if (fsi.size == 0U) { if (directory || fsi.size == 0U) {
return download_type::fallback; return download_type::fallback;
} }
@ -465,8 +477,10 @@ auto file_manager::open(
}; };
auto type = get_download_type(config_.get_preferred_download_type()); auto type = get_download_type(config_.get_preferred_download_type());
event_system::instance().raise<download_type_selected>( if (not directory) {
fsi.api_path, fsi.source_path, type); event_system::instance().raise<download_type_selected>(
fsi.api_path, fsi.source_path, type);
}
switch (type) { switch (type) {
case repertory::download_type::direct: { case repertory::download_type::direct: {
@ -568,7 +582,7 @@ 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) {
return remove_resume(api_path, source_path, false); remove_resume(api_path, source_path, false);
} }
void file_manager::remove_resume(const std::string &api_path, void file_manager::remove_resume(const std::string &api_path,
@ -711,8 +725,8 @@ auto file_manager::rename_directory(const std::string &from_api_path,
} }
auto file_manager::rename_file(const std::string &from_api_path, auto file_manager::rename_file(const std::string &from_api_path,
const std::string &to_api_path, const std::string &to_api_path, bool overwrite)
bool overwrite) -> api_error { -> api_error {
if (not provider_.is_rename_supported()) { if (not provider_.is_rename_supported()) {
return api_error::not_implemented; return api_error::not_implemented;
} }
@ -931,10 +945,10 @@ void file_manager::swap_renamed_items(std::string from_api_path,
auto file_iter = open_file_lookup_.find(from_api_path); auto file_iter = open_file_lookup_.find(from_api_path);
if (file_iter != open_file_lookup_.end()) { if (file_iter != open_file_lookup_.end()) {
auto ptr = std::move(open_file_lookup_[from_api_path]); auto closeable_file = std::move(open_file_lookup_[from_api_path]);
open_file_lookup_.erase(from_api_path); open_file_lookup_.erase(from_api_path);
ptr->set_api_path(to_api_path); closeable_file->set_api_path(to_api_path);
open_file_lookup_[to_api_path] = std::move(ptr); open_file_lookup_[to_api_path] = std::move(closeable_file);
} }
if (directory) { if (directory) {

View File

@ -246,7 +246,8 @@ void open_file::download_chunk(std::size_t chunk, bool skip_active,
read_state_.count(), get_api_error()); read_state_.count(), get_api_error());
if (get_api_error() == api_error::success) { if (get_api_error() == api_error::success) {
auto progress = (static_cast<double>(read_state_.count()) / auto progress = (static_cast<double>(read_state_.count()) /
static_cast<double>(read_state_.size()) * 100.0); static_cast<double>(read_state_.size())) *
100.0;
event_system::instance().raise<download_progress>( event_system::instance().raise<download_progress>(
fsi_.api_path, fsi_.source_path, progress); fsi_.api_path, fsi_.source_path, progress);
if (read_state_.all() && not notified_) { if (read_state_.all() && not notified_) {

View File

@ -22,6 +22,7 @@
#include "file_manager/ring_buffer_open_file.hpp" #include "file_manager/ring_buffer_open_file.hpp"
#include "app_config.hpp" #include "app_config.hpp"
#include "events/event_system.hpp"
#include "file_manager/events.hpp" #include "file_manager/events.hpp"
#include "file_manager/open_file_base.hpp" #include "file_manager/open_file_base.hpp"
#include "platform/platform.hpp" #include "platform/platform.hpp"
@ -69,7 +70,7 @@ ring_buffer_open_file::ring_buffer_open_file(std::string buffer_directory,
source_path_ = source_path_ =
utils::path::combine(buffer_directory, {utils::create_uuid_string()}); utils::path::combine(buffer_directory, {utils::create_uuid_string()});
nf_ = utils::file::file::open_or_create_file(source_path_); nf_ = utils::file::file::open_or_create_file(source_path_);
if (not *nf_) { if (not*nf_) {
throw std::runtime_error(fmt::format("failed to create buffer file|err|{}", throw std::runtime_error(fmt::format("failed to create buffer file|err|{}",
utils::get_last_error_code())); utils::get_last_error_code()));
} }
@ -79,6 +80,10 @@ ring_buffer_open_file::ring_buffer_open_file(std::string buffer_directory,
throw std::runtime_error(fmt::format("failed to resize buffer file|err|{}", throw std::runtime_error(fmt::format("failed to resize buffer file|err|{}",
utils::get_last_error_code())); utils::get_last_error_code()));
} }
reader_thread_ =
std::make_unique<std::thread>([this]() { background_reader_thread(); });
event_system::instance().raise<download_begin>(fsi_.api_path, source_path_);
} }
ring_buffer_open_file::~ring_buffer_open_file() { ring_buffer_open_file::~ring_buffer_open_file() {
@ -92,6 +97,53 @@ ring_buffer_open_file::~ring_buffer_open_file() {
function_name, fsi_.api_path, source_path_, function_name, fsi_.api_path, source_path_,
utils::get_last_error_code(), "failed to delete file"); utils::get_last_error_code(), "failed to delete file");
} }
reader_thread_->join();
reader_thread_.reset();
}
void ring_buffer_open_file::background_reader_thread() {
unique_mutex_lock chunk_lock(chunk_mtx_);
auto next_chunk = ring_pos_;
chunk_notify_.notify_all();
chunk_lock.unlock();
while (not stop_requested_) {
chunk_lock.lock();
next_chunk = next_chunk + 1U > ring_end_ ? ring_begin_ : next_chunk + 1U;
const auto check_and_wait = [this, &chunk_lock, &next_chunk]() {
if (stop_requested_) {
chunk_notify_.notify_all();
chunk_lock.unlock();
return;
}
if (get_read_state().all()) {
chunk_notify_.wait(chunk_lock);
next_chunk = ring_pos_;
}
chunk_notify_.notify_all();
chunk_lock.unlock();
};
if (not ring_state_[next_chunk % ring_state_.size()]) {
check_and_wait();
continue;
}
chunk_notify_.notify_all();
chunk_lock.unlock();
download_chunk(next_chunk, true);
chunk_lock.lock();
check_and_wait();
}
event_system::instance().raise<download_end>(fsi_.api_path, source_path_,
api_error::download_stopped);
} }
auto ring_buffer_open_file::can_handle_file(std::uint64_t file_size, auto ring_buffer_open_file::can_handle_file(std::uint64_t file_size,
@ -102,60 +154,97 @@ auto ring_buffer_open_file::can_handle_file(std::uint64_t file_size,
auto ring_buffer_open_file::close() -> bool { auto ring_buffer_open_file::close() -> bool {
stop_requested_ = true; stop_requested_ = true;
unique_mutex_lock chunk_lock(chunk_mtx_);
chunk_notify_.notify_all();
chunk_lock.unlock();
return open_file_base::close(); return open_file_base::close();
} }
auto ring_buffer_open_file::download_chunk(std::size_t chunk) -> api_error { auto ring_buffer_open_file::download_chunk(std::size_t chunk, bool skip_active)
-> api_error {
unique_mutex_lock chunk_lock(chunk_mtx_); unique_mutex_lock chunk_lock(chunk_mtx_);
if (active_downloads_.find(chunk) != active_downloads_.end()) { const auto unlock_and_notify = [this, &chunk_lock]() {
auto active_download = active_downloads_.at(chunk);
chunk_notify_.notify_all(); chunk_notify_.notify_all();
chunk_lock.unlock(); chunk_lock.unlock();
};
const auto unlock_and_return =
[&unlock_and_notify](api_error res) -> api_error {
unlock_and_notify();
return res;
};
if (chunk < ring_begin_ || chunk > ring_end_) {
return unlock_and_return(api_error::invalid_ring_buffer_position);
}
if (active_downloads_.find(chunk) != active_downloads_.end()) {
if (skip_active) {
return unlock_and_return(api_error::success);
}
auto active_download = active_downloads_.at(chunk);
unlock_and_notify();
return active_download->wait(); return active_download->wait();
} }
if (ring_state_[chunk % ring_state_.size()]) { if (not ring_state_[chunk % ring_state_.size()]) {
auto active_download{std::make_shared<download>()}; return unlock_and_return(api_error::success);
active_downloads_[chunk] = active_download;
ring_state_[chunk % ring_state_.size()] = false;
chunk_notify_.notify_all();
chunk_lock.unlock();
data_buffer buffer;
auto data_offset{chunk * chunk_size_};
auto data_size{
chunk == (total_chunks_ - 1U) ? last_chunk_size_ : chunk_size_,
};
auto res{
provider_.read_file_bytes(fsi_.api_path, data_size, data_offset, buffer,
stop_requested_),
};
if (res == api_error::success) {
res = do_io([&]() -> api_error {
std::size_t bytes_written{};
if (nf_->write(buffer, (chunk % ring_state_.size()) * chunk_size_,
&bytes_written)) {
return api_error::success;
}
return api_error::os_error;
});
}
active_download->notify(res);
chunk_lock.lock();
active_downloads_.erase(chunk);
chunk_notify_.notify_all();
return res;
} }
chunk_notify_.notify_all(); auto active_download{std::make_shared<download>()};
chunk_lock.unlock(); active_downloads_[chunk] = active_download;
ring_state_[chunk % ring_state_.size()] = false;
unlock_and_notify();
return api_error::success; data_buffer buffer;
auto data_offset{chunk * chunk_size_};
auto data_size{
chunk == (total_chunks_ - 1U) ? last_chunk_size_ : chunk_size_,
};
event_system::instance().raise<download_chunk_begin>(
fsi_.api_path, source_path_, chunk, get_read_state().size(),
get_read_state().count());
auto res{
provider_.read_file_bytes(fsi_.api_path, data_size, data_offset, buffer,
stop_requested_),
};
chunk_lock.lock();
if (res == api_error::success) {
auto progress =
(static_cast<double>(chunk + 1U) / static_cast<double>(total_chunks_)) *
100.0;
event_system::instance().raise<download_progress>(fsi_.api_path,
source_path_, progress);
res = (chunk >= ring_begin_ && chunk <= ring_end_)
? do_io([&]() -> api_error {
std::size_t bytes_written{};
if (nf_->write(buffer,
(chunk % ring_state_.size()) * chunk_size_,
&bytes_written)) {
return api_error::success;
}
return api_error::os_error;
})
: api_error::invalid_ring_buffer_position;
}
event_system::instance().raise<download_chunk_end>(
fsi_.api_path, source_path_, chunk, get_read_state().size(),
get_read_state().count(), res);
active_downloads_.erase(chunk);
unlock_and_notify();
active_download->notify(res);
return res;
} }
void ring_buffer_open_file::forward(std::size_t count) { void ring_buffer_open_file::forward(std::size_t count) {
@ -179,6 +268,7 @@ void ring_buffer_open_file::forward(std::size_t count) {
ring_begin_ += added; ring_begin_ += added;
ring_pos_ += count; ring_pos_ += count;
} }
ring_end_ = ring_end_ =
std::min(total_chunks_ - 1U, ring_begin_ + ring_state_.size() - 1U); std::min(total_chunks_ - 1U, ring_begin_ + ring_state_.size() - 1U);
} }
@ -204,9 +294,7 @@ auto ring_buffer_open_file::native_operation(
void 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_); mutex_lock chunk_lock(chunk_mtx_);
if (ring_pos_ < count) { count = std::min(ring_pos_, count);
count = ring_pos_;
}
if ((ring_pos_ - count) >= ring_begin_) { if ((ring_pos_ - count) >= ring_begin_) {
ring_pos_ -= count; ring_pos_ -= count;
@ -232,16 +320,14 @@ void ring_buffer_open_file::reverse(std::size_t count) {
} }
auto ring_buffer_open_file::read(std::size_t read_size, auto ring_buffer_open_file::read(std::size_t read_size,
std::uint64_t read_offset, std::uint64_t read_offset, data_buffer &data)
data_buffer &data) -> api_error { -> api_error {
if (fsi_.directory) { if (fsi_.directory) {
return api_error::invalid_operation; return api_error::invalid_operation;
} }
reset_timeout(); reset_timeout();
mutex_lock lock(read_mtx_);
read_size = utils::calculate_read_size(fsi_.size, read_size, read_offset); read_size = utils::calculate_read_size(fsi_.size, read_size, read_offset);
if (read_size == 0U) { if (read_size == 0U) {
return api_error::success; return api_error::success;
@ -251,6 +337,8 @@ auto ring_buffer_open_file::read(std::size_t read_size,
read_offset = read_offset - (begin_chunk * chunk_size_); read_offset = read_offset - (begin_chunk * chunk_size_);
auto res{api_error::success}; auto res{api_error::success};
unique_mutex_lock read_lock(read_mtx_);
for (std::size_t chunk = begin_chunk; for (std::size_t chunk = begin_chunk;
(res == api_error::success) && (read_size > 0U); ++chunk) { (res == api_error::success) && (read_size > 0U); ++chunk) {
if (chunk > ring_pos_) { if (chunk > ring_pos_) {
@ -259,10 +347,16 @@ auto ring_buffer_open_file::read(std::size_t read_size,
reverse(ring_pos_ - chunk); reverse(ring_pos_ - chunk);
} }
reset_timeout(); res = download_chunk(chunk, false);
res = download_chunk(chunk);
if (res != api_error::success) { if (res != api_error::success) {
if (not stop_requested_ &&
res == api_error::invalid_ring_buffer_position) {
read_lock.unlock();
// TODO limit retry
return read(read_size, read_offset, data);
}
return res; return res;
} }

View File

@ -25,8 +25,8 @@
#include "utils/string.hpp" #include "utils/string.hpp"
namespace repertory { namespace repertory {
auto database_type_from_string(std::string type, auto database_type_from_string(std::string type, database_type default_type)
database_type default_type) -> database_type { -> database_type {
type = utils::string::to_lower(utils::string::trim(type)); type = utils::string::to_lower(utils::string::trim(type));
if (type == "rocksdb") { if (type == "rocksdb") {
return database_type::rocksdb; return database_type::rocksdb;
@ -50,8 +50,8 @@ auto database_type_to_string(const database_type &type) -> std::string {
} }
} }
auto download_type_from_string(std::string type, auto download_type_from_string(std::string type, download_type default_type)
download_type default_type) -> download_type { -> download_type {
type = utils::string::to_lower(utils::string::trim(type)); type = utils::string::to_lower(utils::string::trim(type));
if (type == "direct") { if (type == "direct") {
return download_type::direct; return download_type::direct;
@ -106,6 +106,7 @@ static const std::unordered_map<api_error, std::string> LOOKUP = {
{api_error::invalid_handle, "invalid_handle"}, {api_error::invalid_handle, "invalid_handle"},
{api_error::invalid_operation, "invalid_operation"}, {api_error::invalid_operation, "invalid_operation"},
{api_error::invalid_ring_buffer_multiple, "invalid_ring_buffer_multiple"}, {api_error::invalid_ring_buffer_multiple, "invalid_ring_buffer_multiple"},
{api_error::invalid_ring_buffer_position, "invalid_ring_buffer_position"},
{api_error::invalid_ring_buffer_size, "invalid_ring_buffer_size"}, {api_error::invalid_ring_buffer_size, "invalid_ring_buffer_size"},
{api_error::invalid_version, "invalid_version"}, {api_error::invalid_version, "invalid_version"},
{api_error::item_exists, "item_exists"}, {api_error::item_exists, "item_exists"},

View File

@ -29,12 +29,22 @@ constexpr const std::size_t test_chunk_size{1024U};
} // namespace } // namespace
namespace repertory { namespace repertory {
TEST(direct_open_file, read_full_file) { class direct_open_file_test : public ::testing::Test {
public:
console_consumer con_consumer;
mock_provider provider;
protected:
void SetUp() override { event_system::instance().start(); }
void TearDown() override { event_system::instance().stop(); }
};
TEST_F(direct_open_file_test, read_full_file) {
auto &source_file = test::create_random_file(test_chunk_size * 32U); auto &source_file = test::create_random_file(test_chunk_size * 32U);
auto dest_path = test::generate_test_file_name("direct_open_file"); auto dest_path = test::generate_test_file_name("direct_open_file");
mock_provider provider;
EXPECT_CALL(provider, is_read_only()).WillRepeatedly(Return(false)); EXPECT_CALL(provider, is_read_only()).WillRepeatedly(Return(false));
filesystem_item fsi; filesystem_item fsi;
@ -89,12 +99,11 @@ TEST(direct_open_file, read_full_file) {
} }
} }
TEST(direct_open_file, read_full_file_in_reverse) { TEST_F(direct_open_file_test, read_full_file_in_reverse) {
auto &source_file = test::create_random_file(test_chunk_size * 32U); auto &source_file = test::create_random_file(test_chunk_size * 32U);
auto dest_path = test::generate_test_file_name("direct_open_file"); auto dest_path = test::generate_test_file_name("direct_open_file");
mock_provider provider;
EXPECT_CALL(provider, is_read_only()).WillRepeatedly(Return(false)); EXPECT_CALL(provider, is_read_only()).WillRepeatedly(Return(false));
filesystem_item fsi; filesystem_item fsi;
@ -149,12 +158,11 @@ TEST(direct_open_file, read_full_file_in_reverse) {
} }
} }
TEST(direct_open_file, read_full_file_in_partial_chunks) { TEST_F(direct_open_file_test, read_full_file_in_partial_chunks) {
auto &source_file = test::create_random_file(test_chunk_size * 32U); auto &source_file = test::create_random_file(test_chunk_size * 32U);
auto dest_path = test::generate_test_file_name("test"); auto dest_path = test::generate_test_file_name("test");
mock_provider provider;
EXPECT_CALL(provider, is_read_only()).WillRepeatedly(Return(false)); EXPECT_CALL(provider, is_read_only()).WillRepeatedly(Return(false));
filesystem_item fsi; filesystem_item fsi;
@ -206,12 +214,11 @@ TEST(direct_open_file, read_full_file_in_partial_chunks) {
} }
} }
TEST(direct_open_file, read_full_file_in_partial_chunks_in_reverse) { TEST_F(direct_open_file_test, read_full_file_in_partial_chunks_in_reverse) {
auto &source_file = test::create_random_file(test_chunk_size * 32U); auto &source_file = test::create_random_file(test_chunk_size * 32U);
auto dest_path = test::generate_test_file_name("direct_open_file"); auto dest_path = test::generate_test_file_name("direct_open_file");
mock_provider provider;
EXPECT_CALL(provider, is_read_only()).WillRepeatedly(Return(false)); EXPECT_CALL(provider, is_read_only()).WillRepeatedly(Return(false));
filesystem_item fsi; filesystem_item fsi;

View File

@ -30,9 +30,11 @@
#include "utils/event_capture.hpp" #include "utils/event_capture.hpp"
#include "utils/path.hpp" #include "utils/path.hpp"
namespace repertory { namespace {
static constexpr const std::size_t test_chunk_size{1024U}; constexpr const std::size_t test_chunk_size{1024U};
}
namespace repertory {
class open_file_test : public ::testing::Test { class open_file_test : public ::testing::Test {
public: public:
console_consumer con_consumer; console_consumer con_consumer;

View File

@ -31,18 +31,29 @@
namespace { namespace {
constexpr const std::size_t test_chunk_size{1024U}; constexpr const std::size_t test_chunk_size{1024U};
std::string ring_buffer_dir = repertory::utils::path::combine( const auto ring_buffer_dir{
repertory::test::get_test_output_dir(), repertory::utils::path::combine(
{"file_manager_ring_buffer_open_file_test"}); repertory::test::get_test_output_dir(),
{"file_manager_ring_buffer_open_file_test"}),
};
} // namespace } // namespace
namespace repertory { namespace repertory {
TEST(ring_buffer_open_file, can_forward_to_last_chunk) { class ring_buffer_open_file_test : public ::testing::Test {
public:
console_consumer con_consumer;
mock_provider provider;
protected:
void SetUp() override { event_system::instance().start(); }
void TearDown() override { event_system::instance().stop(); }
};
TEST_F(ring_buffer_open_file_test, can_forward_to_last_chunk) {
auto source_path = test::generate_test_file_name("ring_buffer_open_file"); auto source_path = test::generate_test_file_name("ring_buffer_open_file");
mock_provider prov; EXPECT_CALL(provider, is_read_only()).WillRepeatedly(Return(false));
EXPECT_CALL(prov, is_read_only()).WillRepeatedly(Return(false));
filesystem_item fsi; filesystem_item fsi;
fsi.directory = false; fsi.directory = false;
@ -51,8 +62,8 @@ TEST(ring_buffer_open_file, can_forward_to_last_chunk) {
fsi.source_path = source_path; fsi.source_path = source_path;
{ {
ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi, prov, ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi,
8U); provider, 8U);
file.set(0U, 3U); file.set(0U, 3U);
file.forward(4U); file.forward(4U);
@ -63,17 +74,13 @@ TEST(ring_buffer_open_file, can_forward_to_last_chunk) {
EXPECT_TRUE(file.get_read_state(chunk)); EXPECT_TRUE(file.get_read_state(chunk));
} }
} }
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
} }
TEST(ring_buffer_open_file, TEST_F(ring_buffer_open_file_test,
can_forward_to_last_chunk_if_count_is_greater_than_remaining) { can_forward_to_last_chunk_if_count_is_greater_than_remaining) {
auto source_path = test::generate_test_file_name("ring_buffer_open_file"); auto source_path = test::generate_test_file_name("ring_buffer_open_file");
mock_provider prov; EXPECT_CALL(provider, is_read_only()).WillRepeatedly(Return(false));
EXPECT_CALL(prov, is_read_only()).WillRepeatedly(Return(false));
filesystem_item fsi; filesystem_item fsi;
fsi.directory = false; fsi.directory = false;
@ -82,8 +89,8 @@ TEST(ring_buffer_open_file,
fsi.source_path = source_path; fsi.source_path = source_path;
{ {
ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi, prov, ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi,
8U); provider, 8U);
file.set(0U, 3U); file.set(0U, 3U);
file.forward(100U); file.forward(100U);
@ -94,16 +101,12 @@ TEST(ring_buffer_open_file,
EXPECT_FALSE(file.get_read_state(chunk)); EXPECT_FALSE(file.get_read_state(chunk));
} }
} }
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
} }
TEST(ring_buffer_open_file, can_forward_after_last_chunk) { TEST_F(ring_buffer_open_file_test, can_forward_after_last_chunk) {
auto source_path = test::generate_test_file_name("ring_buffer_open_file"); auto source_path = test::generate_test_file_name("ring_buffer_open_file");
mock_provider prov; EXPECT_CALL(provider, is_read_only()).WillRepeatedly(Return(false));
EXPECT_CALL(prov, is_read_only()).WillRepeatedly(Return(false));
filesystem_item fsi; filesystem_item fsi;
fsi.directory = false; fsi.directory = false;
@ -112,8 +115,8 @@ TEST(ring_buffer_open_file, can_forward_after_last_chunk) {
fsi.source_path = source_path; fsi.source_path = source_path;
{ {
ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi, prov, ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi,
8U); provider, 8U);
file.set(0U, 3U); file.set(0U, 3U);
file.forward(5U); file.forward(5U);
@ -125,16 +128,12 @@ TEST(ring_buffer_open_file, can_forward_after_last_chunk) {
EXPECT_TRUE(file.get_read_state(chunk)); EXPECT_TRUE(file.get_read_state(chunk));
} }
} }
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
} }
TEST(ring_buffer_open_file, can_forward_and_rollover_after_last_chunk) { TEST_F(ring_buffer_open_file_test, can_forward_and_rollover_after_last_chunk) {
auto source_path = test::generate_test_file_name("ring_buffer_open_file"); auto source_path = test::generate_test_file_name("ring_buffer_open_file");
mock_provider prov; EXPECT_CALL(provider, is_read_only()).WillRepeatedly(Return(false));
EXPECT_CALL(prov, is_read_only()).WillRepeatedly(Return(false));
filesystem_item fsi; filesystem_item fsi;
fsi.directory = false; fsi.directory = false;
@ -143,8 +142,8 @@ TEST(ring_buffer_open_file, can_forward_and_rollover_after_last_chunk) {
fsi.source_path = source_path; fsi.source_path = source_path;
{ {
ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi, prov, ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi,
8U); provider, 8U);
file.set(16U, 20U); file.set(16U, 20U);
file.forward(8U); file.forward(8U);
@ -152,16 +151,12 @@ TEST(ring_buffer_open_file, can_forward_and_rollover_after_last_chunk) {
EXPECT_EQ(std::size_t(21U), file.get_first_chunk()); EXPECT_EQ(std::size_t(21U), file.get_first_chunk());
EXPECT_EQ(std::size_t(28U), file.get_last_chunk()); EXPECT_EQ(std::size_t(28U), file.get_last_chunk());
} }
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
} }
TEST(ring_buffer_open_file, can_reverse_to_first_chunk) { TEST_F(ring_buffer_open_file_test, can_reverse_to_first_chunk) {
auto source_path = test::generate_test_file_name("ring_buffer_open_file"); auto source_path = test::generate_test_file_name("ring_buffer_open_file");
mock_provider prov; EXPECT_CALL(provider, is_read_only()).WillRepeatedly(Return(false));
EXPECT_CALL(prov, is_read_only()).WillRepeatedly(Return(false));
filesystem_item fsi; filesystem_item fsi;
fsi.directory = false; fsi.directory = false;
@ -170,8 +165,8 @@ TEST(ring_buffer_open_file, can_reverse_to_first_chunk) {
fsi.source_path = source_path; fsi.source_path = source_path;
{ {
ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi, prov, ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi,
8U); provider, 8U);
file.set(0U, 3U); file.set(0U, 3U);
file.reverse(3U); file.reverse(3U);
@ -182,17 +177,13 @@ TEST(ring_buffer_open_file, can_reverse_to_first_chunk) {
EXPECT_TRUE(file.get_read_state(chunk)); EXPECT_TRUE(file.get_read_state(chunk));
} }
} }
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
} }
TEST(ring_buffer_open_file, TEST_F(ring_buffer_open_file_test,
can_reverse_to_first_chunk_if_count_is_greater_than_remaining) { can_reverse_to_first_chunk_if_count_is_greater_than_remaining) {
auto source_path = test::generate_test_file_name("ring_buffer_open_file"); auto source_path = test::generate_test_file_name("ring_buffer_open_file");
mock_provider prov; EXPECT_CALL(provider, is_read_only()).WillRepeatedly(Return(false));
EXPECT_CALL(prov, is_read_only()).WillRepeatedly(Return(false));
filesystem_item fsi; filesystem_item fsi;
fsi.directory = false; fsi.directory = false;
@ -201,8 +192,8 @@ TEST(ring_buffer_open_file,
fsi.source_path = source_path; fsi.source_path = source_path;
{ {
ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi, prov, ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi,
8U); provider, 8U);
file.set(0U, 3U); file.set(0U, 3U);
file.reverse(13U); file.reverse(13U);
@ -213,16 +204,12 @@ TEST(ring_buffer_open_file,
EXPECT_TRUE(file.get_read_state(chunk)); EXPECT_TRUE(file.get_read_state(chunk));
} }
} }
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
} }
TEST(ring_buffer_open_file, can_reverse_before_first_chunk) { TEST_F(ring_buffer_open_file_test, can_reverse_before_first_chunk) {
auto source_path = test::generate_test_file_name("ring_buffer_open_file"); auto source_path = test::generate_test_file_name("ring_buffer_open_file");
mock_provider prov; EXPECT_CALL(provider, is_read_only()).WillRepeatedly(Return(false));
EXPECT_CALL(prov, is_read_only()).WillRepeatedly(Return(false));
filesystem_item fsi; filesystem_item fsi;
fsi.directory = false; fsi.directory = false;
@ -231,8 +218,8 @@ TEST(ring_buffer_open_file, can_reverse_before_first_chunk) {
fsi.source_path = source_path; fsi.source_path = source_path;
{ {
ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi, prov, ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi,
8U); provider, 8U);
file.set(1U, 3U); file.set(1U, 3U);
file.reverse(3U); file.reverse(3U);
@ -244,16 +231,13 @@ TEST(ring_buffer_open_file, can_reverse_before_first_chunk) {
EXPECT_TRUE(file.get_read_state(chunk)); EXPECT_TRUE(file.get_read_state(chunk));
} }
} }
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
} }
TEST(ring_buffer_open_file, can_reverse_and_rollover_before_first_chunk) { TEST_F(ring_buffer_open_file_test,
can_reverse_and_rollover_before_first_chunk) {
auto source_path = test::generate_test_file_name("ring_buffer_open_file"); auto source_path = test::generate_test_file_name("ring_buffer_open_file");
mock_provider prov; EXPECT_CALL(provider, is_read_only()).WillRepeatedly(Return(false));
EXPECT_CALL(prov, is_read_only()).WillRepeatedly(Return(false));
filesystem_item fsi; filesystem_item fsi;
fsi.directory = false; fsi.directory = false;
@ -262,8 +246,8 @@ TEST(ring_buffer_open_file, can_reverse_and_rollover_before_first_chunk) {
fsi.source_path = source_path; fsi.source_path = source_path;
{ {
ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi, prov, ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi,
8U); provider, 8U);
file.set(16U, 20U); file.set(16U, 20U);
file.reverse(8U); file.reverse(8U);
@ -279,16 +263,12 @@ TEST(ring_buffer_open_file, can_reverse_and_rollover_before_first_chunk) {
EXPECT_TRUE(file.get_read_state(chunk)); EXPECT_TRUE(file.get_read_state(chunk));
} }
} }
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
} }
TEST(ring_buffer_open_file, can_reverse_full_ring) { TEST_F(ring_buffer_open_file_test, can_reverse_full_ring) {
auto source_path = test::generate_test_file_name("ring_buffer_open_file"); auto source_path = test::generate_test_file_name("ring_buffer_open_file");
mock_provider prov; EXPECT_CALL(provider, is_read_only()).WillRepeatedly(Return(false));
EXPECT_CALL(prov, is_read_only()).WillRepeatedly(Return(false));
filesystem_item fsi; filesystem_item fsi;
fsi.directory = false; fsi.directory = false;
@ -297,8 +277,8 @@ TEST(ring_buffer_open_file, can_reverse_full_ring) {
fsi.source_path = source_path; fsi.source_path = source_path;
{ {
ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi, prov, ring_buffer_open_file file(ring_buffer_dir, test_chunk_size, 30U, fsi,
8U); provider, 8U);
file.set(8U, 15U); file.set(8U, 15U);
file.reverse(16U); file.reverse(16U);
@ -310,11 +290,9 @@ TEST(ring_buffer_open_file, can_reverse_full_ring) {
EXPECT_FALSE(file.get_read_state(chunk)); EXPECT_FALSE(file.get_read_state(chunk));
} }
} }
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
} }
TEST(ring_buffer_open_file, read_full_file) { TEST_F(ring_buffer_open_file_test, read_full_file) {
auto &nf = test::create_random_file(test_chunk_size * 33u + 11u); auto &nf = test::create_random_file(test_chunk_size * 33u + 11u);
auto download_source_path = nf.get_path(); auto download_source_path = nf.get_path();
@ -375,11 +353,9 @@ TEST(ring_buffer_open_file, read_full_file) {
EXPECT_STREQ(hash1.value().c_str(), hash2.value().c_str()); EXPECT_STREQ(hash1.value().c_str(), hash2.value().c_str());
} }
} }
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
} }
TEST(ring_buffer_open_file, read_full_file_in_reverse) { TEST_F(ring_buffer_open_file_test, read_full_file_in_reverse) {
auto &nf = test::create_random_file(test_chunk_size * 32u); auto &nf = test::create_random_file(test_chunk_size * 32u);
auto download_source_path = nf.get_path(); auto download_source_path = nf.get_path();
@ -417,15 +393,15 @@ TEST(ring_buffer_open_file, read_full_file_in_reverse) {
EXPECT_TRUE(nf2); EXPECT_TRUE(nf2);
auto to_read = fsi.size; auto to_read = fsi.size;
std::size_t chunk = rb.get_total_chunks() - 1u; std::size_t chunk = rb.get_total_chunks() - 1U;
while (to_read) { while (to_read > 0U) {
data_buffer data{}; data_buffer data{};
EXPECT_EQ(api_error::success, EXPECT_EQ(api_error::success,
rb.read(test_chunk_size, chunk * test_chunk_size, data)); rb.read(test_chunk_size, chunk * test_chunk_size, data));
std::size_t bytes_written{}; std::size_t bytes_written{};
EXPECT_TRUE(nf2.write(data, chunk * test_chunk_size, &bytes_written)); EXPECT_TRUE(nf2.write(data, chunk * test_chunk_size, &bytes_written));
chunk--; --chunk;
to_read -= data.size(); to_read -= data.size();
} }
nf2.close(); nf2.close();
@ -440,11 +416,9 @@ TEST(ring_buffer_open_file, read_full_file_in_reverse) {
EXPECT_STREQ(hash1.value().c_str(), hash2.value().c_str()); EXPECT_STREQ(hash1.value().c_str(), hash2.value().c_str());
} }
} }
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
} }
TEST(ring_buffer_open_file, read_full_file_in_partial_chunks) { TEST_F(ring_buffer_open_file_test, read_full_file_in_partial_chunks) {
auto &nf = test::create_random_file(test_chunk_size * 32u); auto &nf = test::create_random_file(test_chunk_size * 32u);
auto download_source_path = nf.get_path(); auto download_source_path = nf.get_path();
@ -506,11 +480,10 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks) {
EXPECT_STREQ(hash1.value().c_str(), hash2.value().c_str()); EXPECT_STREQ(hash1.value().c_str(), hash2.value().c_str());
} }
} }
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
} }
TEST(ring_buffer_open_file, read_full_file_in_partial_chunks_in_reverse) { TEST_F(ring_buffer_open_file_test,
read_full_file_in_partial_chunks_in_reverse) {
auto &nf = test::create_random_file(test_chunk_size * 32u); auto &nf = test::create_random_file(test_chunk_size * 32u);
auto download_source_path = nf.get_path(); auto download_source_path = nf.get_path();
@ -577,7 +550,5 @@ TEST(ring_buffer_open_file, read_full_file_in_partial_chunks_in_reverse) {
EXPECT_STREQ(hash1.value().c_str(), hash2.value().c_str()); EXPECT_STREQ(hash1.value().c_str(), hash2.value().c_str());
} }
} }
EXPECT_TRUE(utils::file::directory(ring_buffer_dir).remove_recursively());
} }
} // namespace repertory } // namespace repertory