Loading REPLICA.md 0 → 100644 +1178 −0 File added.Preview size limit exceeded, changes collapsed. Show changes src/client/preload_context.cpp +7 −4 Changes for src/client/preload_context.cpp: 7 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -1604,8 +1604,10 @@ PreloadContext::enqueue_metadata_size_repairs( const bool append, const bool clear_inline, const std::vector<int8_t>& failed_copies) { std::lock_guard<std::mutex> lock(repair_queue_mutex_); const auto kind = append ? gkfs::rpc::repair_kind::deferred : gkfs::rpc::repair_kind::metadata_size; // Append changes still use the metadata-size executor. The append flag and // reserved offset are stored in the task; deferred is only a queue // predicate sentinel and is intentionally not executable by workers. const auto kind = gkfs::rpc::repair_kind::metadata_size; const auto generation = current_repair_generation(path, kind); for(const auto target_copy : failed_copies) { gkfs::rpc::repair_task task; Loading @@ -1629,8 +1631,9 @@ PreloadContext::enqueue_metadata_inline_repairs( const std::string& path, const std::string& data, const uint64_t offset, const bool append, const std::vector<int8_t>& failed_copies) { std::lock_guard<std::mutex> lock(repair_queue_mutex_); const auto kind = append ? gkfs::rpc::repair_kind::deferred : gkfs::rpc::repair_kind::metadata_inline; // Append inline writes are executable metadata-inline repairs. The append // flag remains part of the task payload; deferred tasks are not executable. const auto kind = gkfs::rpc::repair_kind::metadata_inline; const auto generation = current_repair_generation(path, kind); for(const auto target_copy : failed_copies) { gkfs::rpc::repair_task task; Loading tests/unit/test_repair_queue.cpp +36 −0 Changes for tests/unit/test_repair_queue.cpp: 36 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -180,3 +180,39 @@ TEST_CASE("repair queue snapshot preserves pending tasks", "[replication][repair REQUIRE(snapshot.front().retry_count == 2); REQUIRE(snapshot.front().generation == 9); } TEST_CASE("repair queue keeps append metadata repairs executable", "[replication][repair]") { gkfs::rpc::repair_queue queue; const auto now = std::chrono::steady_clock::now(); gkfs::rpc::repair_task size_task{"/append", 0, 0, 1, 4, 0, EIO, now}; size_task.kind = gkfs::rpc::repair_kind::metadata_size; size_task.append = true; size_task.offset = 128; REQUIRE(queue.enqueue(size_task)); gkfs::rpc::repair_task inline_task{"/append", 0, 0, 1, 5, 0, EIO, now}; inline_task.kind = gkfs::rpc::repair_kind::metadata_inline; inline_task.append = true; inline_task.data = "payload"; REQUIRE(queue.enqueue(inline_task)); const auto first = queue.pop_ready( [](const auto& task) { return task.kind != gkfs::rpc::repair_kind::deferred; }, now); REQUIRE(first); REQUIRE(first->append); REQUIRE(first->kind == gkfs::rpc::repair_kind::metadata_size); const auto second = queue.pop_ready( [](const auto& task) { return task.kind != gkfs::rpc::repair_kind::deferred; }, now); REQUIRE(second); REQUIRE(second->append); REQUIRE(second->kind == gkfs::rpc::repair_kind::metadata_inline); } No newline at end of file Loading
REPLICA.md 0 → 100644 +1178 −0 File added.Preview size limit exceeded, changes collapsed. Show changes
src/client/preload_context.cpp +7 −4 Changes for src/client/preload_context.cpp: 7 added lines, 4 removed lines. Original line number Diff line number Diff line Loading @@ -1604,8 +1604,10 @@ PreloadContext::enqueue_metadata_size_repairs( const bool append, const bool clear_inline, const std::vector<int8_t>& failed_copies) { std::lock_guard<std::mutex> lock(repair_queue_mutex_); const auto kind = append ? gkfs::rpc::repair_kind::deferred : gkfs::rpc::repair_kind::metadata_size; // Append changes still use the metadata-size executor. The append flag and // reserved offset are stored in the task; deferred is only a queue // predicate sentinel and is intentionally not executable by workers. const auto kind = gkfs::rpc::repair_kind::metadata_size; const auto generation = current_repair_generation(path, kind); for(const auto target_copy : failed_copies) { gkfs::rpc::repair_task task; Loading @@ -1629,8 +1631,9 @@ PreloadContext::enqueue_metadata_inline_repairs( const std::string& path, const std::string& data, const uint64_t offset, const bool append, const std::vector<int8_t>& failed_copies) { std::lock_guard<std::mutex> lock(repair_queue_mutex_); const auto kind = append ? gkfs::rpc::repair_kind::deferred : gkfs::rpc::repair_kind::metadata_inline; // Append inline writes are executable metadata-inline repairs. The append // flag remains part of the task payload; deferred tasks are not executable. const auto kind = gkfs::rpc::repair_kind::metadata_inline; const auto generation = current_repair_generation(path, kind); for(const auto target_copy : failed_copies) { gkfs::rpc::repair_task task; Loading
tests/unit/test_repair_queue.cpp +36 −0 Changes for tests/unit/test_repair_queue.cpp: 36 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -180,3 +180,39 @@ TEST_CASE("repair queue snapshot preserves pending tasks", "[replication][repair REQUIRE(snapshot.front().retry_count == 2); REQUIRE(snapshot.front().generation == 9); } TEST_CASE("repair queue keeps append metadata repairs executable", "[replication][repair]") { gkfs::rpc::repair_queue queue; const auto now = std::chrono::steady_clock::now(); gkfs::rpc::repair_task size_task{"/append", 0, 0, 1, 4, 0, EIO, now}; size_task.kind = gkfs::rpc::repair_kind::metadata_size; size_task.append = true; size_task.offset = 128; REQUIRE(queue.enqueue(size_task)); gkfs::rpc::repair_task inline_task{"/append", 0, 0, 1, 5, 0, EIO, now}; inline_task.kind = gkfs::rpc::repair_kind::metadata_inline; inline_task.append = true; inline_task.data = "payload"; REQUIRE(queue.enqueue(inline_task)); const auto first = queue.pop_ready( [](const auto& task) { return task.kind != gkfs::rpc::repair_kind::deferred; }, now); REQUIRE(first); REQUIRE(first->append); REQUIRE(first->kind == gkfs::rpc::repair_kind::metadata_size); const auto second = queue.pop_ready( [](const auto& task) { return task.kind != gkfs::rpc::repair_kind::deferred; }, now); REQUIRE(second); REQUIRE(second->append); REQUIRE(second->kind == gkfs::rpc::repair_kind::metadata_inline); } No newline at end of file