Loading include/client/rpc/repair_journal_lock.hpp +30 −2 Changes for include/client/rpc/repair_journal_lock.hpp: 30 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -19,6 +19,9 @@ #include <chrono> #include <cstdint> #include <cstring> #include <fstream> #include <iomanip> #include <sstream> #include <stdexcept> #include <string> #include <sys/types.h> Loading @@ -29,8 +32,31 @@ struct repair_journal_owner { std::string hostname; pid_t pid{}; uint64_t acquired_at{}; std::string topology_identity; }; inline std::string repair_journal_topology_identity(const std::string& hostfile_path) { std::ifstream input(hostfile_path, std::ios::binary); if(!input.is_open()) { return "unavailable"; } constexpr uint64_t fnv_offset = 14695981039346656037ULL; constexpr uint64_t fnv_prime = 1099511628211ULL; uint64_t hash = fnv_offset; char byte{}; while(input.get(byte)) { hash ^= static_cast<uint64_t>(static_cast<unsigned char>(byte)); hash *= fnv_prime; } std::ostringstream result; result << "fnv1a-64:" << std::hex << std::setw(16) << std::setfill('0') << hash; return result.str(); } /** * @brief Owns the advisory process lock for a client-local repair journal. * Loading @@ -50,7 +76,8 @@ public: } void acquire(const std::string& journal_path) { acquire(const std::string& journal_path, const std::string& topology_identity = "unknown") { if(journal_path.empty() || fd_) { return; } Loading Loading @@ -93,11 +120,12 @@ public: std::chrono::duration_cast<std::chrono::seconds>( std::chrono::system_clock::now().time_since_epoch()) .count()); owner.topology_identity = topology_identity; const auto record = "hostname=" + owner.hostname + "\n" + "pid=" + std::to_string(owner.pid) + "\n" + "acquired_at=" + std::to_string(owner.acquired_at) + "\n"; "\n" + "topology=" + owner.topology_identity + "\n"; if(::ftruncate(candidate.get(), 0) != 0 || ::write(candidate.get(), record.data(), record.size()) != static_cast<ssize_t>(record.size())) { Loading src/client/preload_context.cpp +5 −1 Changes for src/client/preload_context.cpp: 5 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -106,7 +106,11 @@ PreloadContext::PreloadContext() PreloadContext::set_replicas(replicas); repair_status_path_ = gkfs::env::get_var(gkfs::env::REPAIR_STATUS_PATH); repair_journal_path_ = gkfs::env::get_var(gkfs::env::REPAIR_JOURNAL_PATH); repair_journal_lock_.acquire(repair_journal_path_); const auto hostfile_path = gkfs::env::get_var(gkfs::env::HOSTS_FILE, gkfs::config::hostfile_path); repair_journal_lock_.acquire( repair_journal_path_, gkfs::rpc::repair_journal_topology_identity(hostfile_path)); const std::string env_dirents_buff_size = gkfs::env::get_var(gkfs::env::DIRENTS_BUFF_SIZE); Loading tests/unit/test_repair_journal_lock.cpp +11 −1 Changes for tests/unit/test_repair_journal_lock.cpp: 11 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -29,17 +29,26 @@ test_journal_path() { TEST_CASE("repair journal lock has exclusive process ownership", "[replication][repair][journal]") { const auto journal = test_journal_path(); const auto hostfile = journal.string() + ".hosts"; const auto lock_path = journal.string() + ".lock"; std::filesystem::remove(lock_path); { std::ofstream output(hostfile); output << "host-a fi+sockets://127.0.0.1:1234\n"; } const auto topology = gkfs::rpc::repair_journal_topology_identity(hostfile); REQUIRE(topology.rfind("fnv1a-64:", 0) == 0); { gkfs::rpc::repair_journal_lock first; first.acquire(journal.string()); first.acquire(journal.string(), topology); REQUIRE(first.owns_lock()); REQUIRE(first.path() == lock_path); REQUIRE(first.owner().pid == ::getpid()); REQUIRE_FALSE(first.owner().hostname.empty()); REQUIRE(first.owner().acquired_at > 0); REQUIRE(first.owner().topology_identity == topology); std::ifstream owner_record(lock_path); std::stringstream contents; Loading @@ -59,6 +68,7 @@ TEST_CASE("repair journal lock has exclusive process ownership", REQUIRE(after_release.owns_lock()); after_release.release(); std::filesystem::remove(lock_path); std::filesystem::remove(hostfile); } TEST_CASE("empty repair journal path does not create a lock", Loading Loading
include/client/rpc/repair_journal_lock.hpp +30 −2 Changes for include/client/rpc/repair_journal_lock.hpp: 30 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -19,6 +19,9 @@ #include <chrono> #include <cstdint> #include <cstring> #include <fstream> #include <iomanip> #include <sstream> #include <stdexcept> #include <string> #include <sys/types.h> Loading @@ -29,8 +32,31 @@ struct repair_journal_owner { std::string hostname; pid_t pid{}; uint64_t acquired_at{}; std::string topology_identity; }; inline std::string repair_journal_topology_identity(const std::string& hostfile_path) { std::ifstream input(hostfile_path, std::ios::binary); if(!input.is_open()) { return "unavailable"; } constexpr uint64_t fnv_offset = 14695981039346656037ULL; constexpr uint64_t fnv_prime = 1099511628211ULL; uint64_t hash = fnv_offset; char byte{}; while(input.get(byte)) { hash ^= static_cast<uint64_t>(static_cast<unsigned char>(byte)); hash *= fnv_prime; } std::ostringstream result; result << "fnv1a-64:" << std::hex << std::setw(16) << std::setfill('0') << hash; return result.str(); } /** * @brief Owns the advisory process lock for a client-local repair journal. * Loading @@ -50,7 +76,8 @@ public: } void acquire(const std::string& journal_path) { acquire(const std::string& journal_path, const std::string& topology_identity = "unknown") { if(journal_path.empty() || fd_) { return; } Loading Loading @@ -93,11 +120,12 @@ public: std::chrono::duration_cast<std::chrono::seconds>( std::chrono::system_clock::now().time_since_epoch()) .count()); owner.topology_identity = topology_identity; const auto record = "hostname=" + owner.hostname + "\n" + "pid=" + std::to_string(owner.pid) + "\n" + "acquired_at=" + std::to_string(owner.acquired_at) + "\n"; "\n" + "topology=" + owner.topology_identity + "\n"; if(::ftruncate(candidate.get(), 0) != 0 || ::write(candidate.get(), record.data(), record.size()) != static_cast<ssize_t>(record.size())) { Loading
src/client/preload_context.cpp +5 −1 Changes for src/client/preload_context.cpp: 5 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -106,7 +106,11 @@ PreloadContext::PreloadContext() PreloadContext::set_replicas(replicas); repair_status_path_ = gkfs::env::get_var(gkfs::env::REPAIR_STATUS_PATH); repair_journal_path_ = gkfs::env::get_var(gkfs::env::REPAIR_JOURNAL_PATH); repair_journal_lock_.acquire(repair_journal_path_); const auto hostfile_path = gkfs::env::get_var(gkfs::env::HOSTS_FILE, gkfs::config::hostfile_path); repair_journal_lock_.acquire( repair_journal_path_, gkfs::rpc::repair_journal_topology_identity(hostfile_path)); const std::string env_dirents_buff_size = gkfs::env::get_var(gkfs::env::DIRENTS_BUFF_SIZE); Loading
tests/unit/test_repair_journal_lock.cpp +11 −1 Changes for tests/unit/test_repair_journal_lock.cpp: 11 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -29,17 +29,26 @@ test_journal_path() { TEST_CASE("repair journal lock has exclusive process ownership", "[replication][repair][journal]") { const auto journal = test_journal_path(); const auto hostfile = journal.string() + ".hosts"; const auto lock_path = journal.string() + ".lock"; std::filesystem::remove(lock_path); { std::ofstream output(hostfile); output << "host-a fi+sockets://127.0.0.1:1234\n"; } const auto topology = gkfs::rpc::repair_journal_topology_identity(hostfile); REQUIRE(topology.rfind("fnv1a-64:", 0) == 0); { gkfs::rpc::repair_journal_lock first; first.acquire(journal.string()); first.acquire(journal.string(), topology); REQUIRE(first.owns_lock()); REQUIRE(first.path() == lock_path); REQUIRE(first.owner().pid == ::getpid()); REQUIRE_FALSE(first.owner().hostname.empty()); REQUIRE(first.owner().acquired_at > 0); REQUIRE(first.owner().topology_identity == topology); std::ifstream owner_record(lock_path); std::stringstream contents; Loading @@ -59,6 +68,7 @@ TEST_CASE("repair journal lock has exclusive process ownership", REQUIRE(after_release.owns_lock()); after_release.release(); std::filesystem::remove(lock_path); std::filesystem::remove(hostfile); } TEST_CASE("empty repair journal path does not create a lock", Loading