diff --git a/repertory/librepertory/include/drives/remote/remote_open_file_table.hpp b/repertory/librepertory/include/drives/remote/remote_open_file_table.hpp index 45072bee..804ccc90 100644 --- a/repertory/librepertory/include/drives/remote/remote_open_file_table.hpp +++ b/repertory/librepertory/include/drives/remote/remote_open_file_table.hpp @@ -33,25 +33,32 @@ protected: virtual ~remote_open_file_table() = default; protected: - struct compat_open_info { - std::size_t count{0U}; + struct compat_open_info final { std::string client_id; + std::vector handles; std::string path; }; - struct open_info { - std::size_t count{0U}; + struct open_info final { std::string client_id; PVOID directory_buffer{nullptr}; + std::vector handles; std::string path; }; private: - std::unordered_map compat_lookup_; - std::recursive_mutex compat_mutex_; + std::unordered_map> + compat_file_lookup_; + std::unordered_map compat_handle_lookup_; + +private: std::unordered_map> directory_lookup_; - std::recursive_mutex directory_mutex_; - std::unordered_map file_lookup_; + +private: + std::unordered_map> file_lookup_; + std::unordered_map handle_lookup_; + +private: mutable std::recursive_mutex file_mutex_; protected: @@ -64,11 +71,11 @@ protected: PVOID *&buffer) -> bool; #endif // _WIN32 - [[nodiscard]] auto - get_open_file_path(const native_handle &handle) -> std::string; + [[nodiscard]] auto get_open_file_path(const native_handle &handle) + -> std::string; - [[nodiscard]] auto get_open_info(const native_handle &handle, - open_info &oi) -> bool; + [[nodiscard]] auto get_open_info(const native_handle &handle, open_info &oi) + -> bool; [[nodiscard]] auto has_open_directory(const std::string &client_id, std::uint64_t handle) -> bool; @@ -77,20 +84,21 @@ protected: int error_return) -> int; template - [[nodiscard]] auto - has_open_info(const native_handle &handle, - const error_type &error_return) -> error_type { + [[nodiscard]] auto has_open_info(const native_handle &handle, + const error_type &error_return) + -> error_type { recur_mutex_lock file_lock(file_mutex_); - return ((file_lookup_.find(handle) == file_lookup_.end()) ? error_return - : 0); + return handle_lookup_.contains(handle) ? 0 : error_return; } void remove_all(const std::string &file_path); + void remove_and_close_all(const native_handle &handle); + void remove_compat_open_info(const remote::file_handle &handle); - auto remove_directory(const std::string &client_id, - std::uint64_t handle) -> bool; + auto remove_directory(const std::string &client_id, std::uint64_t handle) + -> bool; void remove_open_info(const native_handle &handle); @@ -102,11 +110,11 @@ protected: void set_compat_open_info(const remote::file_handle &handle, const std::string &file_path); - void set_open_info(const native_handle &handle, open_info oi); + void set_open_info(const native_handle &handle, open_info op_info); public: - [[nodiscard]] auto - get_open_file_count(const std::string &file_path) const -> std::size_t; + [[nodiscard]] auto get_open_file_count(const std::string &file_path) const + -> std::size_t; }; } // namespace repertory diff --git a/repertory/librepertory/include/drives/remote/remote_server_base.hpp b/repertory/librepertory/include/drives/remote/remote_server_base.hpp index eab0c180..2823897b 100644 --- a/repertory/librepertory/include/drives/remote/remote_server_base.hpp +++ b/repertory/librepertory/include/drives/remote/remote_server_base.hpp @@ -137,12 +137,12 @@ public: if (ret == STATUS_SUCCESS) { #if defined(_WIN32) this->set_client_id(file_desc, client_id); -#else +#else // !defined(_WIN32) this->set_client_id( static_cast( reinterpret_cast(file_desc)), client_id); -#endif +#endif // defined(_WIN32) response.encode(file_desc); response.encode(file_info); response.encode(normalized_name); @@ -277,12 +277,12 @@ public: if (ret == STATUS_SUCCESS) { #if defined(_WIN32) this->set_client_id(file_desc, client_id); -#else +#else // !defined(_WIN32) this->set_client_id( static_cast( reinterpret_cast(file_desc)), client_id); -#endif +#endif // defined(_WIN32) response.encode(file_desc); response.encode(file_info); response.encode(normalized_name); @@ -585,9 +585,9 @@ public: 0) { #if defined(_WIN32) this->set_compat_client_id(handle, client_id); -#else +#else // !defined(_WIN32) this->set_client_id(static_cast(handle), client_id); -#endif +#endif // defined(_WIN32) response.encode(handle); } return ret; @@ -841,9 +841,9 @@ public: if ((ret = this->fuse_open(path.c_str(), flags, handle)) >= 0) { #if defined(_WIN32) this->set_compat_client_id(handle, client_id); -#else +#else // !defined(_WIN32) this->set_client_id(static_cast(handle), client_id); -#endif +#endif // defined(_WIN32) response.encode(handle); } return ret; diff --git a/repertory/librepertory/src/drives/remote/remote_open_file_table.cpp b/repertory/librepertory/src/drives/remote/remote_open_file_table.cpp index b4925dfc..7f224d2b 100644 --- a/repertory/librepertory/src/drives/remote/remote_open_file_table.cpp +++ b/repertory/librepertory/src/drives/remote/remote_open_file_table.cpp @@ -24,12 +24,13 @@ #include "events/event_system.hpp" #include "events/events.hpp" #include "utils/collection.hpp" +#include "utils/config.hpp" #include "utils/utils.hpp" namespace repertory { void remote_open_file_table::add_directory(const std::string &client_id, std::uint64_t handle) { - recur_mutex_lock directory_lock(directory_mutex_); + recur_mutex_lock lock(file_mutex_); auto &list = directory_lookup_[client_id]; if (utils::collection::excludes(list, handle)) { directory_lookup_[client_id].emplace_back(handle); @@ -37,14 +38,32 @@ void remote_open_file_table::add_directory(const std::string &client_id, } void remote_open_file_table::close_all(const std::string &client_id) { - std::vector compat_handles; - unique_recur_mutex_lock compat_lock(compat_mutex_); - for (auto &&kv : compat_lookup_) { - if (kv.second.client_id == client_id) { - compat_handles.emplace_back(kv.first); - } - } - compat_lock.unlock(); + unique_recur_mutex_lock lock(file_mutex_); + auto compat_handles = + std::accumulate(compat_file_lookup_.begin(), compat_file_lookup_.end(), + std::vector(), + [&client_id](auto &&list, auto &&value) { + auto &&op_info = value.second; + if (op_info->client_id == client_id) { + list.insert(list.end(), op_info->handles.begin(), + op_info->handles.end()); + } + + return list; + }); + + auto handles = std::accumulate( + file_lookup_.begin(), file_lookup_.end(), std::vector(), + [&client_id](auto &&list, auto &&value) { + auto &&op_info = value.second; + if (op_info->client_id == client_id) { + list.insert(list.end(), op_info->handles.begin(), + op_info->handles.end()); + } + + return list; + }); + lock.unlock(); for (auto &&handle : compat_handles) { #if defined(_WIN32) @@ -55,32 +74,23 @@ void remote_open_file_table::close_all(const std::string &client_id) { remove_compat_open_info(handle); } - std::vector handles; - unique_recur_mutex_lock file_lock(file_mutex_); - for (auto &&kv : file_lookup_) { - if (kv.second.client_id == client_id) { - handles.emplace_back(kv.first); - } - } - file_lock.unlock(); - for (auto &&handle : handles) { #if defined(_WIN32) ::CloseHandle(handle); -#else +#else // !defined(_WIN32) close(handle); -#endif +#endif // defined(_WIN32) remove_open_info(handle); } std::vector dirs; - unique_recur_mutex_lock directory_lock(directory_mutex_); + lock.lock(); for (auto &&kv : directory_lookup_) { if (kv.first == client_id) { dirs.insert(dirs.end(), kv.second.begin(), kv.second.end()); } } - directory_lock.unlock(); + lock.unlock(); for (auto &&dir : dirs) { remove_directory(client_id, dir); @@ -90,123 +100,123 @@ void remote_open_file_table::close_all(const std::string &client_id) { #if defined(_WIN32) auto remote_open_file_table::get_directory_buffer(const native_handle &handle, PVOID *&buffer) -> bool { - recur_mutex_lock file_lock(file_mutex_); - if (file_lookup_.find(handle) != file_lookup_.end()) { - buffer = &file_lookup_[handle].directory_buffer; - return true; + recur_mutex_lock lock(file_mutex_); + if (not handle_lookup_.contains(handle)) { + return false; } - return false; + + buffer = &file_lookup_.at(handle_lookup_.at(handle))->directory_buffer; + return true; } -#endif +#endif // defined(_WIN32) auto remote_open_file_table::get_open_file_count( const std::string &file_path) const -> std::size_t { - unique_recur_mutex_lock file_lock(file_mutex_); - const auto count = std::accumulate( - file_lookup_.cbegin(), file_lookup_.cend(), std::size_t(0U), - [&file_path](std::size_t total, const auto &kv) -> std::size_t { - if (kv.second.path == file_path) { - return ++total; - } - return total; - }); - - return std::accumulate( - compat_lookup_.cbegin(), compat_lookup_.cend(), count, - [&file_path](std::size_t total, const auto &kv) -> std::size_t { - if (kv.second.path == file_path) { - return ++total; - } - return total; - }); + recur_mutex_lock lock(file_mutex_); + return (file_lookup_.contains(file_path) + ? file_lookup_.at(file_path)->handles.size() + : 0ULL) + + (compat_file_lookup_.contains(file_path) + ? compat_file_lookup_.at(file_path)->handles.size() + : 0ULL); } auto remote_open_file_table::get_open_info(const native_handle &handle, open_info &oi) -> bool { - recur_mutex_lock file_lock(file_mutex_); - if (file_lookup_.find(handle) != file_lookup_.end()) { - oi = file_lookup_[handle]; - return true; + recur_mutex_lock lock(file_mutex_); + if (not handle_lookup_.contains(handle)) { + return false; } - return false; + + oi = *file_lookup_.at(handle_lookup_.at(handle)).get(); + return true; } auto remote_open_file_table::get_open_file_path(const native_handle &handle) -> std::string { - recur_mutex_lock file_lock(file_mutex_); - if (file_lookup_.find(handle) != file_lookup_.end()) { - return file_lookup_[handle].path; + recur_mutex_lock lock(file_mutex_); + if (not handle_lookup_.contains(handle)) { + return ""; } - return ""; + return file_lookup_.at(handle_lookup_.at(handle))->path; } auto remote_open_file_table::has_open_directory(const std::string &client_id, std::uint64_t handle) -> bool { - recur_mutex_lock directory_lock(directory_mutex_); - auto &list = directory_lookup_[client_id]; - return (utils::collection::includes(list, handle)); + recur_mutex_lock lock(file_mutex_); + return (utils::collection::includes(directory_lookup_[client_id], handle)); } auto remote_open_file_table::has_compat_open_info( const remote::file_handle &handle, int error_return) -> int { - recur_mutex_lock compat_lock(compat_mutex_); - const auto res = - ((compat_lookup_.find(handle) == compat_lookup_.end()) ? -1 : 0); + recur_mutex_lock compat_lock(file_mutex_); + auto res = compat_handle_lookup_.contains(handle) ? 0 : -1; if (res == -1) { errno = error_return; } + return res; } void remote_open_file_table::remove_all(const std::string &file_path) { - unique_recur_mutex_lock file_lock(file_mutex_); - const auto open_list = std::accumulate( - file_lookup_.begin(), file_lookup_.end(), std::vector(), - [&file_path](std::vector v, - const auto &kv) -> std::vector { - if (kv.second.path == file_path) { - v.emplace_back(kv.first); - } - return v; - }); - - const auto compat_open_list = std::accumulate( - compat_lookup_.begin(), compat_lookup_.end(), + unique_recur_mutex_lock lock(file_mutex_); + auto compat_open_list = std::accumulate( + compat_file_lookup_.begin(), compat_file_lookup_.end(), std::vector(), - [&file_path](std::vector v, - const auto &kv) -> std::vector { - if (kv.second.path == file_path) { - v.emplace_back(kv.first); + [&file_path](auto &&list, auto &&kv) -> std::vector { + if (kv.first == file_path) { + auto *op_info = kv.second.get(); + list.insert(list.end(), op_info->handles.begin(), + op_info->handles.end()); } - return v; + return list; }); - file_lock.unlock(); - for (auto &&handle : open_list) { - remove_open_info(handle); - } + auto open_list = std::accumulate( + file_lookup_.begin(), file_lookup_.end(), std::vector(), + [&file_path](auto &&list, auto &&kv) -> std::vector { + if (kv.first == file_path) { + auto *op_info = kv.second.get(); + list.insert(list.end(), op_info->handles.begin(), + op_info->handles.end()); + } + return list; + }); + lock.unlock(); for (auto &&handle : compat_open_list) { remove_compat_open_info(handle); } + + for (auto &&handle : open_list) { + remove_open_info(handle); + } } void remote_open_file_table::remove_compat_open_info( const remote::file_handle &handle) { - recur_mutex_lock compat_lock(compat_mutex_); - if (compat_lookup_[handle].count > 0) { - compat_lookup_[handle].count--; + recur_mutex_lock compat_lock(file_mutex_); + if (not compat_handle_lookup_.contains(handle)) { + return; } - if (not compat_lookup_[handle].count) { - compat_lookup_.erase(handle); + auto *op_info = + compat_file_lookup_.at(compat_handle_lookup_.at(handle)).get(); + utils::collection::remove_element(op_info->handles, handle); + compat_handle_lookup_.erase(handle); + + if (not op_info->handles.empty()) { + return; } + + auto path = op_info->path; + compat_file_lookup_.erase(path); } auto remote_open_file_table::remove_directory(const std::string &client_id, std::uint64_t handle) -> bool { - recur_mutex_lock directory_lock(directory_mutex_); + recur_mutex_lock lock(file_mutex_); auto &list = directory_lookup_[client_id]; if (utils::collection::includes(list, handle)) { utils::collection::remove_element(list, handle); @@ -220,48 +230,93 @@ auto remote_open_file_table::remove_directory(const std::string &client_id, } void remote_open_file_table::remove_open_info(const native_handle &handle) { - recur_mutex_lock file_lock(file_mutex_); - if (file_lookup_[handle].count > 0) { - file_lookup_[handle].count--; + recur_mutex_lock lock(file_mutex_); + if (not handle_lookup_.contains(handle)) { + return; } - if (not file_lookup_[handle].count) { + + auto *op_info = file_lookup_.at(handle_lookup_.at(handle)).get(); + utils::collection::remove_element(op_info->handles, handle); + handle_lookup_.erase(handle); + + if (not op_info->handles.empty()) { + return; + } + #if defined(_WIN32) - if (file_lookup_[handle].directory_buffer) { - FspFileSystemDeleteDirectoryBuffer( - &file_lookup_[handle].directory_buffer); - } + if (op_info->directory_buffer) { + FspFileSystemDeleteDirectoryBuffer(&op_info->directory_buffer); + } #endif - file_lookup_.erase(handle); + + auto path = op_info->path; + file_lookup_.erase(path); +} + +void remote_open_file_table::remove_and_close_all(const native_handle &handle) { + unique_recur_mutex_lock lock(file_mutex_); + if (not handle_lookup_.contains(handle)) { + return; + } + + auto op_info = *file_lookup_.at(handle_lookup_.at(handle)); + lock.unlock(); + + for (auto &&open_handle : op_info.handles) { +#if defined(_WIN32) + ::CloseHandle(open_handle); +#else // !defined(_WIN32) + close(open_handle); +#endif // defined(_WIN32) + remove_open_info(open_handle); } } void remote_open_file_table::set_compat_client_id( const remote::file_handle &handle, const std::string &client_id) { - recur_mutex_lock compat_lock(compat_mutex_); - compat_lookup_[handle].client_id = client_id; + recur_mutex_lock compat_lock(file_mutex_); + compat_file_lookup_.at(compat_handle_lookup_.at(handle))->client_id = + client_id; } void remote_open_file_table::set_client_id(const native_handle &handle, const std::string &client_id) { - recur_mutex_lock file_lock(file_mutex_); - file_lookup_[handle].client_id = client_id; + recur_mutex_lock lock(file_mutex_); + file_lookup_.at(handle_lookup_.at(handle))->client_id = client_id; } void remote_open_file_table::set_compat_open_info( const remote::file_handle &handle, const std::string &file_path) { - recur_mutex_lock compat_lock(compat_mutex_); - if (compat_lookup_.find(handle) == compat_lookup_.end()) { - compat_lookup_[handle] = {0, "", file_path}; + recur_mutex_lock compat_lock(file_mutex_); + if (compat_handle_lookup_.contains(handle)) { + return; } - compat_lookup_[handle].count++; + + if (not compat_file_lookup_.contains(file_path)) { + compat_file_lookup_[file_path] = + std::make_unique(compat_open_info{ + "", + {}, + file_path, + }); + } + + compat_handle_lookup_[handle] = file_path; + compat_file_lookup_.at(file_path)->handles.emplace_back(handle); } void remote_open_file_table::set_open_info(const native_handle &handle, - open_info oi) { - recur_mutex_lock file_lock(file_mutex_); - if (file_lookup_.find(handle) == file_lookup_.end()) { - file_lookup_[handle] = std::move(oi); + open_info op_info) { + recur_mutex_lock lock(file_mutex_); + if (handle_lookup_.contains(handle)) { + return; } - file_lookup_[handle].count++; + + if (not file_lookup_.contains(op_info.path)) { + file_lookup_[op_info.path] = std::make_unique(op_info); + } + + handle_lookup_[handle] = op_info.path; + file_lookup_.at(op_info.path)->handles.emplace_back(handle); } } // namespace repertory diff --git a/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_client.cpp b/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_client.cpp index 8c736015..a75d3359 100644 --- a/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_client.cpp +++ b/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_client.cpp @@ -160,10 +160,12 @@ auto remote_client::winfsp_cleanup(PVOID file_desc, PWSTR file_name, auto ret{ packet_client_.send(function_name, request, response, service_flags), }; + DECODE_OR_IGNORE(&response, was_closed); if (was_closed != 0U) { remove_all(file_path); } + RAISE_REMOTE_WINFSP_CLIENT_EVENT(function_name, file_path, ret); return ret; } @@ -222,11 +224,16 @@ auto remote_client::winfsp_create(PWSTR file_name, UINT32 create_options, DECODE_OR_IGNORE(&response, *file_info); DECODE_OR_IGNORE(&response, normalized_name); DECODE_OR_IGNORE(&response, exists); + if (ret == STATUS_SUCCESS) { *file_desc = reinterpret_cast(handle); - set_open_info( - to_handle(*file_desc), - open_info{0, "", nullptr, utils::string::to_utf8(file_name)}); + set_open_info(to_handle(*file_desc), + open_info{ + "", + nullptr, + {}, + utils::string::to_utf8(file_name), + }); #if defined(_WIN32) if (exists) { ::SetLastError(ERROR_ALREADY_EXISTS); @@ -390,9 +397,13 @@ auto remote_client::winfsp_open(PWSTR file_name, UINT32 create_options, if (ret == STATUS_SUCCESS) { *file_desc = reinterpret_cast(handle); - set_open_info( - to_handle(*file_desc), - open_info{0, "", nullptr, utils::string::to_utf8(file_name)}); + set_open_info(to_handle(*file_desc), + open_info{ + "", + nullptr, + {}, + utils::string::to_utf8(file_name), + }); } } diff --git a/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_server.cpp b/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_server.cpp index a01a49b6..e8fad2ad 100644 --- a/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_server.cpp +++ b/repertory/librepertory/src/drives/winfsp/remotewinfsp/remote_server.cpp @@ -945,12 +945,12 @@ auto remote_server::winfsp_cleanup(PVOID file_desc, PWSTR /*file_name*/, auto *handle = reinterpret_cast(file_desc); auto ret = has_open_info(handle, STATUS_INVALID_HANDLE); if (ret == STATUS_SUCCESS) { - if ((flags & FileSystemBase::CleanupDelete) != 0U) { - ::CloseHandle(handle); - remove_open_info(file_desc); + if ((flags & FspCleanupDelete) != 0U) { + remove_and_close_all(file_desc); was_closed = TRUE; } } + RAISE_REMOTE_WINFSP_SERVER_EVENT(function_name, file_path, ret); return ret; } @@ -1005,8 +1005,12 @@ auto remote_server::winfsp_create(PWSTR file_name, UINT32 create_options, if (handle != INVALID_HANDLE_VALUE) { *file_desc = reinterpret_cast(handle); normalized_name = utils::string::to_utf8(file_name); - set_open_info(*file_desc, - open_info{0, "", nullptr, utils::string::to_utf8(file_path)}); + set_open_info(*file_desc, open_info{ + "", + nullptr, + {}, + utils::string::to_utf8(file_path), + }); } auto ret = @@ -1140,8 +1144,12 @@ auto remote_server::winfsp_open(PWSTR file_name, UINT32 create_options, if (handle != INVALID_HANDLE_VALUE) { *file_desc = reinterpret_cast(handle); normalized_name = utils::string::to_utf8(file_name); - set_open_info(*file_desc, - open_info{0, "", nullptr, utils::string::to_utf8(file_path)}); + set_open_info(*file_desc, open_info{ + "", + nullptr, + {}, + utils::string::to_utf8(file_path), + }); } auto ret = diff --git a/repertory/librepertory/src/drives/winfsp/winfsp_drive.cpp b/repertory/librepertory/src/drives/winfsp/winfsp_drive.cpp index 347a3367..3ac40e1e 100644 --- a/repertory/librepertory/src/drives/winfsp/winfsp_drive.cpp +++ b/repertory/librepertory/src/drives/winfsp/winfsp_drive.cpp @@ -203,15 +203,15 @@ VOID winfsp_drive::Cleanup(PVOID file_node, PVOID file_desc, FspFileSystemDeleteDirectoryBuffer(&directory_buffer); } - if (directory) { - if (provider_.get_directory_item_count(api_path) == 0) { - return handle_error(provider_.remove_directory(api_path)); - } - - return handle_error(api_error::directory_not_empty); + if (not directory) { + return handle_error(fm_->remove_file(api_path)); } - return handle_error(fm_->remove_file(api_path)); + if (provider_.get_directory_item_count(api_path) == 0) { + return handle_error(provider_.remove_directory(api_path)); + } + + return handle_error(api_error::directory_not_empty); } if (((flags & FspCleanupSetArchiveBit) != 0U) && not directory) {