winfsp unit tests and fixes
This commit is contained in:
parent
489d9b1960
commit
c14b637536
@ -106,7 +106,9 @@ public:
|
||||
|
||||
[[nodiscard]] virtual auto is_write_supported() const -> bool = 0;
|
||||
|
||||
virtual void remove(std::uint64_t handle, bool noQueue = false) = 0;
|
||||
virtual void remove(std::uint64_t handle) = 0;
|
||||
|
||||
virtual void remove_all() = 0;
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
|
@ -107,7 +107,9 @@ public:
|
||||
native_operation_callback callback)
|
||||
-> api_error override;
|
||||
|
||||
void remove(std::uint64_t handle, bool noQueue = false) override;
|
||||
void remove(std::uint64_t handle) override;
|
||||
|
||||
void remove_all() override;
|
||||
|
||||
[[nodiscard]] auto read(std::size_t read_size, std::uint64_t read_offset,
|
||||
data_buffer &data) -> api_error override;
|
||||
|
@ -185,7 +185,9 @@ public:
|
||||
|
||||
[[nodiscard]] auto is_modified() const -> bool override;
|
||||
|
||||
void remove(std::uint64_t handle, bool noQueue = false) override;
|
||||
void remove(std::uint64_t handle) override;
|
||||
|
||||
void remove_all() override;
|
||||
|
||||
void set_api_path(const std::string &api_path) override;
|
||||
};
|
||||
|
@ -128,9 +128,11 @@ file_manager::~file_manager() {
|
||||
void file_manager::close(std::uint64_t handle) {
|
||||
recur_mutex_lock file_lock(open_file_mtx_);
|
||||
auto closeable_file = get_open_file_by_handle(handle);
|
||||
if (closeable_file) {
|
||||
closeable_file->remove(handle, false);
|
||||
if (not closeable_file) {
|
||||
return;
|
||||
}
|
||||
|
||||
closeable_file->remove(handle);
|
||||
}
|
||||
|
||||
void file_manager::close_all(const std::string &api_path) {
|
||||
@ -143,25 +145,9 @@ void file_manager::close_all(const std::string &api_path) {
|
||||
return;
|
||||
}
|
||||
|
||||
remove_upload(api_path, true);
|
||||
|
||||
auto closeable_file = file_iter->second;
|
||||
closeable_file->remove_all();
|
||||
open_file_lookup_.erase(api_path);
|
||||
|
||||
auto handles = closeable_file->get_handles();
|
||||
for (auto &&handle : handles) {
|
||||
closeable_file->remove(handle, true);
|
||||
}
|
||||
|
||||
auto result = utils::db::sqlite::db_delete{*db_, resume_table}
|
||||
.where("api_path")
|
||||
.equals(api_path)
|
||||
.go();
|
||||
if (not result.ok()) {
|
||||
utils::error::raise_api_path_error(function_name, api_path,
|
||||
api_error::error,
|
||||
"failed to remove from resume table");
|
||||
}
|
||||
}
|
||||
|
||||
void file_manager::close_timed_out_files() {
|
||||
|
@ -117,8 +117,8 @@ void open_file::download_chunk(std::size_t chunk, bool skip_active,
|
||||
return;
|
||||
}
|
||||
|
||||
const auto data_offset = chunk * chunk_size_;
|
||||
const auto data_size =
|
||||
auto data_offset = chunk * chunk_size_;
|
||||
auto data_size =
|
||||
(chunk == read_state_.size() - 1U) ? last_chunk_size_ : chunk_size_;
|
||||
if (active_downloads_.empty() && (read_state_.count() == 0U)) {
|
||||
event_system::instance().raise<download_begin>(fsi_.api_path,
|
||||
@ -258,12 +258,12 @@ auto open_file::native_operation(
|
||||
}
|
||||
file_lock.unlock();
|
||||
|
||||
const auto is_empty_file = new_file_size == 0U;
|
||||
const auto last_chunk =
|
||||
is_empty_file ? std::size_t(0U)
|
||||
: static_cast<std::size_t>(utils::divide_with_ceiling(
|
||||
new_file_size, chunk_size_)) -
|
||||
1U;
|
||||
auto is_empty_file = new_file_size == 0U;
|
||||
auto last_chunk = is_empty_file
|
||||
? std::size_t(0U)
|
||||
: static_cast<std::size_t>(utils::divide_with_ceiling(
|
||||
new_file_size, chunk_size_)) -
|
||||
1U;
|
||||
|
||||
file_lock.lock();
|
||||
if (not is_empty_file && (last_chunk < read_state_.size())) {
|
||||
@ -277,7 +277,7 @@ auto open_file::native_operation(
|
||||
file_lock.lock();
|
||||
}
|
||||
|
||||
const auto original_file_size = get_file_size();
|
||||
auto original_file_size = get_file_size();
|
||||
|
||||
auto res = do_io([&]() -> api_error { return callback(nf_->get_handle()); });
|
||||
if (res != api_error::success) {
|
||||
@ -319,7 +319,7 @@ auto open_file::native_operation(
|
||||
set_modified();
|
||||
|
||||
fsi_.size = new_file_size;
|
||||
const auto now = std::to_string(utils::time::get_time_now());
|
||||
auto now = std::to_string(utils::time::get_time_now());
|
||||
res = provider_.set_item_meta(
|
||||
fsi_.api_path, {
|
||||
{META_CHANGED, now},
|
||||
@ -372,8 +372,8 @@ auto open_file::read(std::size_t read_size, std::uint64_t read_offset,
|
||||
}
|
||||
file_lock.unlock();
|
||||
|
||||
const auto start_chunk = static_cast<std::size_t>(read_offset / chunk_size_);
|
||||
const auto end_chunk =
|
||||
auto start_chunk = static_cast<std::size_t>(read_offset / chunk_size_);
|
||||
auto end_chunk =
|
||||
static_cast<std::size_t>((read_size + read_offset) / chunk_size_);
|
||||
|
||||
update_background_reader(start_chunk);
|
||||
@ -388,10 +388,10 @@ auto open_file::read(std::size_t read_size, std::uint64_t read_offset,
|
||||
: get_api_error();
|
||||
}
|
||||
|
||||
void open_file::remove(std::uint64_t handle, bool noQueue) {
|
||||
void open_file::remove(std::uint64_t handle) {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
open_file_base::remove(handle, noQueue);
|
||||
if (not noQueue && modified_ && read_state_.all() &&
|
||||
open_file_base::remove(handle);
|
||||
if (modified_ && read_state_.all() &&
|
||||
(get_api_error() == api_error::success)) {
|
||||
mgr_.queue_upload(*this);
|
||||
modified_ = false;
|
||||
@ -402,6 +402,18 @@ void open_file::remove(std::uint64_t handle, bool noQueue) {
|
||||
}
|
||||
}
|
||||
|
||||
void open_file::remove_all() {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
open_file_base::remove_all();
|
||||
|
||||
modified_ = false;
|
||||
removed_ = true;
|
||||
|
||||
set_api_error(api_error::success);
|
||||
|
||||
mgr_.remove_upload(get_api_path());
|
||||
}
|
||||
|
||||
auto open_file::resize(std::uint64_t new_file_size) -> api_error {
|
||||
if (fsi_.directory) {
|
||||
return api_error::invalid_operation;
|
||||
@ -417,65 +429,70 @@ auto open_file::resize(std::uint64_t new_file_size) -> api_error {
|
||||
auto open_file::close() -> bool {
|
||||
REPERTORY_USES_FUNCTION_NAME();
|
||||
|
||||
if (not fsi_.directory && not stop_requested_) {
|
||||
stop_requested_ = true;
|
||||
if (fsi_.directory || stop_requested_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unique_mutex_lock reader_lock(io_thread_mtx_);
|
||||
io_thread_notify_.notify_all();
|
||||
reader_lock.unlock();
|
||||
stop_requested_ = true;
|
||||
|
||||
if (reader_thread_) {
|
||||
reader_thread_->join();
|
||||
reader_thread_.reset();
|
||||
}
|
||||
unique_mutex_lock reader_lock(io_thread_mtx_);
|
||||
io_thread_notify_.notify_all();
|
||||
reader_lock.unlock();
|
||||
|
||||
if (open_file_base::close()) {
|
||||
{
|
||||
const auto err = get_api_error();
|
||||
if (err == api_error::success ||
|
||||
err == api_error::download_incomplete ||
|
||||
err == api_error::download_stopped) {
|
||||
if (modified_ && not read_state_.all()) {
|
||||
set_api_error(api_error::download_incomplete);
|
||||
} else if (not modified_ && (fsi_.size > 0U) &&
|
||||
not read_state_.all()) {
|
||||
set_api_error(api_error::download_stopped);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nf_->close();
|
||||
|
||||
if (modified_ && (get_api_error() == api_error::success)) {
|
||||
mgr_.queue_upload(*this);
|
||||
} else if (modified_ &&
|
||||
(get_api_error() == api_error::download_incomplete)) {
|
||||
mgr_.store_resume(*this);
|
||||
} else if (get_api_error() != api_error::success) {
|
||||
mgr_.remove_resume(get_api_path(), get_source_path());
|
||||
if (not utils::file::file(fsi_.source_path).remove()) {
|
||||
utils::error::raise_api_path_error(
|
||||
function_name, get_api_path(), fsi_.source_path,
|
||||
utils::get_last_error_code(), "failed to delete file");
|
||||
}
|
||||
|
||||
auto parent = utils::path::get_parent_path(fsi_.source_path);
|
||||
fsi_.source_path =
|
||||
utils::path::combine(parent, {utils::create_uuid_string()});
|
||||
const auto res = provider_.set_item_meta(fsi_.api_path, META_SOURCE,
|
||||
fsi_.source_path);
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(function_name, get_api_path(),
|
||||
fsi_.source_path, res,
|
||||
"failed to set file meta");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (reader_thread_) {
|
||||
reader_thread_->join();
|
||||
reader_thread_.reset();
|
||||
}
|
||||
|
||||
if (not open_file_base::close()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
auto err = get_api_error();
|
||||
if (err == api_error::success || err == api_error::download_incomplete ||
|
||||
err == api_error::download_stopped) {
|
||||
if (modified_ && not read_state_.all()) {
|
||||
set_api_error(api_error::download_incomplete);
|
||||
} else if (not modified_ && (fsi_.size > 0U) && not read_state_.all()) {
|
||||
set_api_error(api_error::download_stopped);
|
||||
}
|
||||
}
|
||||
|
||||
nf_->close();
|
||||
|
||||
if (modified_ && (get_api_error() == api_error::success)) {
|
||||
mgr_.queue_upload(*this);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (modified_ && (get_api_error() == api_error::download_incomplete)) {
|
||||
mgr_.store_resume(*this);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (get_api_error() == api_error::success) {
|
||||
return true;
|
||||
}
|
||||
|
||||
mgr_.remove_resume(get_api_path(), get_source_path());
|
||||
if (not utils::file::file(fsi_.source_path).remove()) {
|
||||
utils::error::raise_api_path_error(
|
||||
function_name, get_api_path(), fsi_.source_path,
|
||||
utils::get_last_error_code(), "failed to delete file");
|
||||
}
|
||||
|
||||
auto parent = utils::path::get_parent_path(fsi_.source_path);
|
||||
fsi_.source_path =
|
||||
utils::path::combine(parent, {utils::create_uuid_string()});
|
||||
auto res =
|
||||
provider_.set_item_meta(fsi_.api_path, META_SOURCE, fsi_.source_path);
|
||||
if (res != api_error::success) {
|
||||
utils::error::raise_api_path_error(function_name, get_api_path(),
|
||||
fsi_.source_path, res,
|
||||
"failed to set file meta");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void open_file::set_modified() {
|
||||
@ -544,8 +561,8 @@ auto open_file::write(std::uint64_t write_offset, const data_buffer &data,
|
||||
}
|
||||
write_lock.unlock();
|
||||
|
||||
const auto start_chunk = static_cast<std::size_t>(write_offset / chunk_size_);
|
||||
const auto end_chunk =
|
||||
auto start_chunk = static_cast<std::size_t>(write_offset / chunk_size_);
|
||||
auto end_chunk =
|
||||
static_cast<std::size_t>((write_offset + data.size()) / chunk_size_);
|
||||
|
||||
update_background_reader(start_chunk);
|
||||
@ -576,7 +593,7 @@ auto open_file::write(std::uint64_t write_offset, const data_buffer &data,
|
||||
return set_api_error(res);
|
||||
}
|
||||
|
||||
const auto now = std::to_string(utils::time::get_time_now());
|
||||
auto now = std::to_string(utils::time::get_time_now());
|
||||
res = provider_.set_item_meta(fsi_.api_path, {
|
||||
{META_CHANGED, now},
|
||||
{META_MODIFIED, now},
|
||||
|
@ -235,7 +235,7 @@ auto open_file_base::is_modified() const -> bool {
|
||||
return modified_;
|
||||
}
|
||||
|
||||
void open_file_base::remove(std::uint64_t handle, bool /* noQueue */) {
|
||||
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>(
|
||||
@ -246,6 +246,20 @@ void open_file_base::remove(std::uint64_t handle, bool /* noQueue */) {
|
||||
}
|
||||
}
|
||||
|
||||
void open_file_base::remove_all() {
|
||||
recur_mutex_lock file_lock(file_mtx_);
|
||||
auto open_data = open_data_;
|
||||
open_data_.clear();
|
||||
|
||||
for (auto &&data : open_data) {
|
||||
event_system::instance().raise<filesystem_item_handle_closed>(
|
||||
fsi_.api_path, data.first, fsi_.source_path, fsi_.directory, modified_);
|
||||
}
|
||||
|
||||
event_system::instance().raise<filesystem_item_closed>(
|
||||
fsi_.api_path, fsi_.source_path, fsi_.directory, modified_);
|
||||
}
|
||||
|
||||
void open_file_base::reset_timeout() {
|
||||
last_access_ = std::chrono::system_clock::now();
|
||||
}
|
||||
|
@ -97,7 +97,9 @@ public:
|
||||
|
||||
MOCK_METHOD(bool, is_write_supported, (), (const, override));
|
||||
|
||||
MOCK_METHOD(void, remove, (std::uint64_t handle, bool noQueue), (override));
|
||||
MOCK_METHOD(void, remove, (std::uint64_t handle), (override));
|
||||
|
||||
MOCK_METHOD(void, remove_all, (), (override));
|
||||
};
|
||||
} // namespace repertory
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user