From 8f8194f0f1392d59b95442ce0b12909675ff3e40 Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Fri, 27 Nov 2020 16:04:14 +0000 Subject: [PATCH 1/4] Ledger recovery considers read-only ledger directories --- src/host/ledger.h | 42 ++++++++++++++++++++++++++++++++++- src/host/test/ledger.cpp | 47 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 85 insertions(+), 4 deletions(-) diff --git a/src/host/ledger.h b/src/host/ledger.h index e03be4ad5805..cdc4ab86977d 100644 --- a/src/host/ledger.h +++ b/src/host/ledger.h @@ -625,6 +625,34 @@ namespace asynchost max_chunk_threshold_size)); } + // Recover last idx from read-only ledger directories + for (const auto& read_dir : read_ledger_dirs) + { + LOG_DEBUG_FMT("Recovering read-only ledger directory \"{}\"", read_dir); + if (!fs::is_directory(read_dir)) + { + throw std::logic_error( + fmt::format("\"{}\" is not a directory", read_dir)); + } + + for (auto const& f : fs::directory_iterator(read_dir)) + { + auto last_idx_ = get_last_idx_from_file_name(f.path().filename()); + if (!last_idx_.has_value()) + { + LOG_DEBUG_FMT( + "Read only ledger file \"{}\" is ignored as not committed", + f.path().filename()); + continue; + } + + if (last_idx_.value() > last_idx) + { + last_idx = last_idx_.value(); + } + } + } + if (fs::is_directory(ledger_dir)) { // If the ledger directory exists, recover ledger files from it @@ -649,7 +677,17 @@ namespace asynchost return a->get_last_idx() < b->get_last_idx(); }); - last_idx = get_latest_file()->get_last_idx(); + auto main_ledger_dir_last_idx = get_latest_file()->get_last_idx(); + if (main_ledger_dir_last_idx < last_idx) + { + throw std::logic_error(fmt::format( + "Ledger directory last idx ({}) is less than read-only " + "ledger directories last idx ({})", + main_ledger_dir_last_idx, + last_idx)); + } + + last_idx = main_ledger_dir_last_idx; for (auto f = files.begin(); f != files.end();) { @@ -686,6 +724,8 @@ namespace asynchost } require_new_file = true; } + + LOG_INFO_FMT("Recovered ledger entries up to {}", last_idx); } Ledger(const Ledger& that) = delete; diff --git a/src/host/test/ledger.cpp b/src/host/test/ledger.cpp index 68e26ef7ae50..e93e1c6d1570 100644 --- a/src/host/test/ledger.cpp +++ b/src/host/test/ledger.cpp @@ -1,9 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the Apache 2.0 License. #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN -#include "../ledger.h" - -#include "../ds/serialized.h" +#include "ds/serialized.h" +#include "host/ledger.h" #include #include @@ -818,4 +817,46 @@ TEST_CASE("Multiple ledger paths") // cannot be read REQUIRE_FALSE(ledger.read_entry(last_idx).has_value()); } +} + +TEST_CASE("Recover from read-only ledger directory only") +{ + static constexpr auto ledger_dir_2 = "ledger_dir_2"; + + fs::remove_all(ledger_dir); + fs::remove_all(ledger_dir_2); + + size_t max_read_cache_size = 2; + size_t chunk_threshold = 30; + size_t chunk_count = 5; + + size_t last_idx = 0; + + INFO("Write many entries on first ledger"); + { + Ledger ledger(ledger_dir, wf, chunk_threshold); + TestEntrySubmitter entry_submitter(ledger); + + // Writing some committed chunks + initialise_ledger(entry_submitter, chunk_threshold, chunk_count); + last_idx = entry_submitter.get_last_idx(); + ledger.commit(last_idx); + } + + INFO("Recover from read-only ledger entry only"); + { + Ledger ledger( + ledger_dir_2, wf, chunk_threshold, max_read_cache_size, {ledger_dir}); + + read_entries_range_from_ledger(ledger, 1, last_idx); + + TestEntrySubmitter entry_submitter(ledger, last_idx); + + for (size_t i = 0; i < chunk_count; i++) + { + entry_submitter.write(true); + } + + read_entries_range_from_ledger(ledger, 1, entry_submitter.get_last_idx()); + } } \ No newline at end of file From fd28a60063d218c68402e0557352fce02b0b0b7a Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Fri, 27 Nov 2020 16:11:47 +0000 Subject: [PATCH 2/4] Committed idx too --- src/host/ledger.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/host/ledger.h b/src/host/ledger.h index cdc4ab86977d..2d077c654944 100644 --- a/src/host/ledger.h +++ b/src/host/ledger.h @@ -649,6 +649,7 @@ namespace asynchost if (last_idx_.value() > last_idx) { last_idx = last_idx_.value(); + committed_idx = last_idx; } } } @@ -725,7 +726,10 @@ namespace asynchost require_new_file = true; } - LOG_INFO_FMT("Recovered ledger entries up to {}", last_idx); + LOG_INFO_FMT( + "Recovered ledger entries up to {}, committed to {}", + last_idx, + committed_idx); } Ledger(const Ledger& that) = delete; From a39792539236038ca322d4aec9e3bfd3135d2bfc Mon Sep 17 00:00:00 2001 From: Julien Maffre Date: Fri, 27 Nov 2020 16:44:18 +0000 Subject: [PATCH 3/4] Format --- src/host/test/ledger.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/host/test/ledger.cpp b/src/host/test/ledger.cpp index e93e1c6d1570..985dba46f6b8 100644 --- a/src/host/test/ledger.cpp +++ b/src/host/test/ledger.cpp @@ -1,9 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the Apache 2.0 License. #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN -#include "ds/serialized.h" #include "host/ledger.h" +#include "ds/serialized.h" + #include #include From 2a405cfc1917a2e74363d95a3920c104a0e6361e Mon Sep 17 00:00:00 2001 From: Julien Maffre <42961061+jumaffre@users.noreply.github.com> Date: Mon, 30 Nov 2020 09:48:50 +0000 Subject: [PATCH 4/4] Update src/host/ledger.h Co-authored-by: Amaury Chamayou --- src/host/ledger.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/host/ledger.h b/src/host/ledger.h index 2d077c654944..36a43be415a6 100644 --- a/src/host/ledger.h +++ b/src/host/ledger.h @@ -641,7 +641,7 @@ namespace asynchost if (!last_idx_.has_value()) { LOG_DEBUG_FMT( - "Read only ledger file \"{}\" is ignored as not committed", + "Read-only ledger file \"{}\" is ignored as not committed", f.path().filename()); continue; } @@ -939,4 +939,4 @@ namespace asynchost }); } }; -} \ No newline at end of file +}