diff --git a/src/replica/duplication/load_from_private_log.cpp b/src/replica/duplication/load_from_private_log.cpp index 16cdcb9239..6b0af82251 100644 --- a/src/replica/duplication/load_from_private_log.cpp +++ b/src/replica/duplication/load_from_private_log.cpp @@ -30,6 +30,7 @@ #include "replica/replica.h" #include "replica_duplicator.h" #include "utils/autoref_ptr.h" +#include "utils/defer.h" #include "utils/error_code.h" #include "utils/errors.h" #include "utils/fail_point.h" @@ -146,6 +147,9 @@ void load_from_private_log::run() void load_from_private_log::find_log_file_to_start() { + _duplicator->set_duplication_plog_checking(true); + auto cleanup = dsn::defer([this]() { _duplicator->set_duplication_plog_checking(false); }); + // `file_map` has already excluded the useless log files during replica init. const auto &file_map = _private_log->get_log_file_map(); diff --git a/src/replica/duplication/load_from_private_log.h b/src/replica/duplication/load_from_private_log.h index 314951354a..bf288ec545 100644 --- a/src/replica/duplication/load_from_private_log.h +++ b/src/replica/duplication/load_from_private_log.h @@ -61,7 +61,6 @@ class load_from_private_log final : public replica_base, /// Find the log file that contains `_start_decree`. void find_log_file_to_start(); - void find_log_file_to_start(const mutation_log::log_file_map_by_index &log_files); void replay_log_block(); @@ -82,6 +81,9 @@ class load_from_private_log final : public replica_base, static constexpr int MAX_ALLOWED_BLOCK_REPEATS{3}; static constexpr int MAX_ALLOWED_FILE_REPEATS{10}; +private: + void find_log_file_to_start(const mutation_log::log_file_map_by_index &log_files); + private: friend class load_from_private_log_test; friend class load_fail_mode_test; diff --git a/src/replica/duplication/replica_duplicator.cpp b/src/replica/duplication/replica_duplicator.cpp index 01c01b4059..10e3964468 100644 --- a/src/replica/duplication/replica_duplicator.cpp +++ b/src/replica/duplication/replica_duplicator.cpp @@ -262,5 +262,10 @@ uint64_t replica_duplicator::get_pending_mutations_count() const return cnt > 0 ? static_cast(cnt) : 0; } +void replica_duplicator::set_duplication_plog_checking(bool checking) +{ + _replica->set_duplication_plog_checking(checking); +} + } // namespace replication } // namespace dsn diff --git a/src/replica/duplication/replica_duplicator.h b/src/replica/duplication/replica_duplicator.h index 7de9a5f199..78e6497840 100644 --- a/src/replica/duplication/replica_duplicator.h +++ b/src/replica/duplication/replica_duplicator.h @@ -137,7 +137,9 @@ class replica_duplicator : public replica_base, public pipeline::base // For metric "dup.pending_mutations_count" uint64_t get_pending_mutations_count() const; - duplication_status::type status() const { return _status; }; + duplication_status::type status() const { return _status; } + + void set_duplication_plog_checking(bool checking); private: friend class duplication_test_base; diff --git a/src/replica/replica.h b/src/replica/replica.h index e552a33b0b..5e0d107d8c 100644 --- a/src/replica/replica.h +++ b/src/replica/replica.h @@ -245,6 +245,11 @@ class replica : public serverlet, public ref_counter, public replica_ba replica_duplicator_manager *get_duplication_manager() const { return _duplication_mgr.get(); } bool is_duplication_master() const { return _is_duplication_master; } bool is_duplication_follower() const { return _is_duplication_follower; } + bool is_duplication_plog_checking() const { return _is_duplication_plog_checking.load(); } + void set_duplication_plog_checking(bool checking) + { + _is_duplication_plog_checking.store(checking); + } // // Backup @@ -625,6 +630,9 @@ class replica : public serverlet, public ref_counter, public replica_ba bool _is_manual_emergency_checkpointing{false}; bool _is_duplication_master{false}; bool _is_duplication_follower{false}; + // Indicate whether the replica is during finding out some private logs to + // load for duplication. It useful to prevent plog GCed unexpectedly. + std::atomic _is_duplication_plog_checking{false}; // backup std::unique_ptr _backup_mgr; diff --git a/src/replica/replica_chkpt.cpp b/src/replica/replica_chkpt.cpp index d255573dd9..ab22ad9f21 100644 --- a/src/replica/replica_chkpt.cpp +++ b/src/replica/replica_chkpt.cpp @@ -146,6 +146,12 @@ void replica::on_checkpoint_timer() return; } + if (is_duplication_plog_checking()) { + LOG_DEBUG_PREFIX("gc_private {}: skip gc because duplication is checking plog files", + enum_to_string(status())); + return; + } + tasking::enqueue(LPC_GARBAGE_COLLECT_LOGS_AND_REPLICAS, &_tracker, [this, plog, cleanable_decree, valid_start_offset] {