delete lock data when not active and mount location is empty

This commit is contained in:
Scott E. Graves 2025-03-25 07:40:59 -05:00
parent 0e0eb9e729
commit dc3bb025bf
4 changed files with 146 additions and 122 deletions

View File

@ -115,6 +115,7 @@ googletest
gpath gpath
gtest_version gtest_version
has_setxattr has_setxattr
hkey
httpapi httpapi
httplib httplib
icudata icudata

View File

@ -31,43 +31,42 @@ class i_provider;
class lock_data final { class lock_data final {
public: public:
explicit lock_data(const provider_type &pt, std::string unique_id /*= ""*/) explicit lock_data(const provider_type &prov, std::string unique_id /*= ""*/)
: pt_(pt), : prov_(prov),
unique_id_(std::move(unique_id)), unique_id_(std::move(unique_id)),
mutex_id_("repertory_" + app_config::get_provider_name(pt) + "_" + mutex_id_("repertory_" + app_config::get_provider_name(prov) + "_" +
unique_id_), unique_id_),
mutex_handle_(::CreateMutex(nullptr, FALSE, &mutex_id_[0u])) {} mutex_handle_(::CreateMutex(nullptr, FALSE, mutex_id_.c_str())) {}
lock_data(const lock_data &) = delete;
lock_data() lock_data(lock_data &&) = delete;
: pt_(provider_type::sia),
unique_id_(""),
mutex_id_(""),
mutex_handle_(INVALID_HANDLE_VALUE) {}
~lock_data() { release(); } ~lock_data() { release(); }
auto operator=(const lock_data &) -> lock_data & = delete;
auto operator=(lock_data &&) -> lock_data & = delete;
private: private:
const provider_type pt_; provider_type prov_;
const std::string unique_id_; std::string unique_id_;
const std::string mutex_id_; std::string mutex_id_;
HANDLE mutex_handle_; HANDLE mutex_handle_{};
DWORD mutex_state_ = WAIT_FAILED; DWORD mutex_state_{WAIT_FAILED};
public: public:
[[nodiscard]] auto get_mount_state(const provider_type &pt, [[nodiscard]] auto get_mount_state(provider_type prov, json &mount_state)
json &mount_state) -> bool; -> bool;
[[nodiscard]] auto get_mount_state(json &mount_state) -> bool; [[nodiscard]] static auto get_mount_state(json &mount_state) -> bool;
[[nodiscard]] auto get_unique_id() const -> std::string { return unique_id_; } [[nodiscard]] auto get_unique_id() const -> std::string { return unique_id_; }
[[nodiscard]] auto grab_lock(std::uint8_t retry_count = 30) -> lock_result; [[nodiscard]] auto grab_lock(std::uint8_t retry_count = 30U) -> lock_result;
void release(); void release();
[[nodiscard]] auto set_mount_state(bool active, [[nodiscard]] auto set_mount_state(bool active,
const std::string &mount_location, std::string_view mount_location,
const std::int64_t &pid) -> bool; std::int64_t pid) -> bool;
}; };
[[nodiscard]] auto create_meta_attributes( [[nodiscard]] auto create_meta_attributes(

View File

@ -159,7 +159,11 @@ auto lock_data::set_mount_state(bool active, const std::string &mount_location,
{"Location", active ? mount_location : ""}, {"Location", active ? mount_location : ""},
{"PID", active ? pid : -1}, {"PID", active ? pid : -1},
}; };
ret = utils::file::write_json_file(get_lock_data_file(), json_data); if (mount_location.empty() && not active) {
ret = utils::file::file{get_lock_data_file()}.delete();
} else {
ret = utils::file::write_json_file(get_lock_data_file(), json_data);
}
} else { } else {
ret = true; ret = true;
} }

View File

@ -26,131 +26,151 @@
#include "events/event_system.hpp" #include "events/event_system.hpp"
#include "events/types/filesystem_item_added.hpp" #include "events/types/filesystem_item_added.hpp"
#include "providers/i_provider.hpp" #include "providers/i_provider.hpp"
#include "utils/error_utils.hpp"
#include "utils/string.hpp" #include "utils/string.hpp"
namespace repertory { namespace repertory {
auto lock_data::get_mount_state(const provider_type & /*pt*/, json &mount_state) auto lock_data::get_mount_state(provider_type /*pt*/, json &mount_state)
-> bool { -> bool {
const auto ret = get_mount_state(mount_state); if (not get_mount_state(mount_state)) {
if (ret) { return false;
const auto mount_id =
app_config::get_provider_display_name(pt_) + unique_id_;
mount_state = mount_state[mount_id].empty()
? json({{"Active", false}, {"Location", ""}, {"PID", -1}})
: mount_state[mount_id];
} }
return ret; auto mount_id = app_config::get_provider_display_name(prov_) + unique_id_;
mount_state = mount_state[mount_id].empty() ? json({
{"Active", false},
{"Location", ""},
{"PID", -1},
})
: mount_state[mount_id];
return true;
} }
auto lock_data::get_mount_state(json &mount_state) -> bool { auto lock_data::get_mount_state(json &mount_state) -> bool {
HKEY key; HKEY key{};
auto ret = !::RegCreateKeyEx( auto ret = (::RegCreateKeyEx(
HKEY_CURRENT_USER, HKEY_CURRENT_USER,
("SOFTWARE\\" + std::string{REPERTORY_DATA_NAME} + "\\Mounts").c_str(), 0, ("SOFTWARE\\" + std::string{REPERTORY_DATA_NAME} + "\\Mounts")
nullptr, 0, KEY_ALL_ACCESS, nullptr, &key, nullptr); .c_str(),
if (ret) { 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &key,
DWORD i = 0u; nullptr) == ERROR_SUCCESS);
DWORD data_size = 0u; if (not ret) {
std::string name; return ret;
name.resize(32767u);
auto name_size = static_cast<DWORD>(name.size());
while (ret &&
(::RegEnumValue(key, i, &name[0], &name_size, nullptr, nullptr,
nullptr, &data_size) == ERROR_SUCCESS)) {
std::string data;
data.resize(data_size);
name_size++;
if ((ret = !::RegEnumValue(key, i++, &name[0], &name_size, nullptr,
nullptr, reinterpret_cast<LPBYTE>(&data[0]),
&data_size))) {
mount_state[name.c_str()] = json::parse(data);
name_size = static_cast<DWORD>(name.size());
data_size = 0u;
}
}
::RegCloseKey(key);
} }
std::string data;
DWORD data_size{};
DWORD idx{};
std::string name;
name.resize(32767U);
auto name_size{static_cast<DWORD>(name.size())};
while (ret &&
(::RegEnumValue(key, idx, name.data(), &name_size, nullptr, nullptr,
nullptr, &data_size) == ERROR_SUCCESS)) {
data.resize(data_size);
ret = (::RegEnumValue(key, idx, name.data(), &name_size, nullptr, nullptr,
reinterpret_cast<LPBYTE>(data.data()),
&data_size) == ERROR_SUCCESS);
if (ret) {
mount_state[name] = json::parse(data);
name_size = static_cast<DWORD>(name.size());
data_size = 0U;
}
++idx;
}
::RegCloseKey(key);
return ret; return ret;
} }
auto lock_data::grab_lock(std::uint8_t retry_count) -> lock_result { auto lock_data::grab_lock(std::uint8_t retry_count) -> lock_result {
REPERTORY_USES_FUNCTION_NAME();
auto ret = lock_result::success;
if (mutex_handle_ == INVALID_HANDLE_VALUE) { if (mutex_handle_ == INVALID_HANDLE_VALUE) {
ret = lock_result::failure; return lock_result::failure;
} else {
for (auto i = 0;
(i <= retry_count) && ((mutex_state_ = ::WaitForSingleObject(
mutex_handle_, 100)) == WAIT_TIMEOUT);
i++) {
}
switch (mutex_state_) {
case WAIT_OBJECT_0:
ret = lock_result::success;
break;
case WAIT_TIMEOUT:
ret = lock_result::locked;
break;
default:
ret = lock_result::failure;
break;
}
} }
return ret; for (std::uint8_t idx = 0U;
(idx <= retry_count) && ((mutex_state_ = ::WaitForSingleObject(
mutex_handle_, 100)) == WAIT_TIMEOUT);
++idx) {
}
switch (mutex_state_) {
case WAIT_OBJECT_0:
return lock_result::success;
case WAIT_TIMEOUT:
return lock_result::locked;
default:
return lock_result::failure;
}
} }
void lock_data::release() { void lock_data::release() {
if (mutex_handle_ != INVALID_HANDLE_VALUE) { if (mutex_handle_ == INVALID_HANDLE_VALUE) {
if ((mutex_state_ == WAIT_OBJECT_0) || (mutex_state_ == WAIT_ABANDONED)) { return;
::ReleaseMutex(mutex_handle_);
}
::CloseHandle(mutex_handle_);
mutex_handle_ = INVALID_HANDLE_VALUE;
} }
if ((mutex_state_ == WAIT_OBJECT_0) || (mutex_state_ == WAIT_ABANDONED)) {
::ReleaseMutex(mutex_handle_);
}
::CloseHandle(mutex_handle_);
mutex_handle_ = INVALID_HANDLE_VALUE;
} }
auto lock_data::set_mount_state(bool active, const std::string &mount_location, auto lock_data::set_mount_state(bool active, std::string_view mount_location,
const std::int64_t &pid) -> bool { std::int64_t pid) -> bool {
auto ret = false; if (mutex_handle_ == INVALID_HANDLE_VALUE) {
if (mutex_handle_ != INVALID_HANDLE_VALUE) { return false;
const auto mount_id =
app_config::get_provider_display_name(pt_) + unique_id_;
json mount_state;
[[maybe_unused]] auto success = get_mount_state(mount_state);
if ((mount_state.find(mount_id) == mount_state.end()) ||
(mount_state[mount_id].find("Active") == mount_state[mount_id].end()) ||
(mount_state[mount_id]["Active"].get<bool>() != active) ||
(active && ((mount_state[mount_id].find("Location") ==
mount_state[mount_id].end()) ||
(mount_state[mount_id]["Location"].get<std::string>() !=
mount_location)))) {
HKEY key;
if ((ret = !::RegCreateKeyEx(
HKEY_CURRENT_USER,
("SOFTWARE\\" + std::string{REPERTORY_DATA_NAME} + "\\Mounts")
.c_str(),
0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &key, nullptr))) {
const auto str = json({{"Active", active},
{"Location", active ? mount_location : ""},
{"PID", active ? pid : -1}})
.dump(0);
ret = !::RegSetValueEx(key, &mount_id[0], 0, REG_SZ,
reinterpret_cast<const BYTE *>(&str[0]),
static_cast<DWORD>(str.size()));
::RegCloseKey(key);
}
} else {
ret = true;
}
} }
auto mount_id{app_config::get_provider_display_name(prov_) + unique_id_};
json mount_state;
[[maybe_unused]] auto success{get_mount_state(mount_state)};
if (not((mount_state.find(mount_id) == mount_state.end()) ||
(mount_state[mount_id].find("Active") ==
mount_state[mount_id].end()) ||
(mount_state[mount_id]["Active"].get<bool>() != active) ||
(active && ((mount_state[mount_id].find("Location") ==
mount_state[mount_id].end()) ||
(mount_state[mount_id]["Location"].get<std::string>() !=
mount_location))))) {
return true;
}
HKEY key{};
if (::RegCreateKeyEx(
HKEY_CURRENT_USER,
("SOFTWARE\\" + std::string{REPERTORY_DATA_NAME} + "\\Mounts")
.c_str(),
0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &key,
nullptr) != ERROR_SUCCESS) {
return false;
}
auto data{
json({
{"Active", active},
{"Location", active ? mount_location : ""},
{"PID", active ? pid : -1},
})
.dump(),
};
auto ret{false};
if (mount_location.empty() && not active) {
ret = (::RegDeleteKey(key, mount_id.c_str()) == ERROR_SUCCESS);
} else {
ret = (::RegSetValueEx(key, mount_id.c_str(), 0, REG_SZ,
reinterpret_cast<const BYTE *>(data.c_str()),
static_cast<DWORD>(data.size())) == ERROR_SUCCESS);
}
::RegCloseKey(key);
return ret; return ret;
} }