| 2705 | } |
| 2706 | |
| 2707 | bool Chainstate::FlushStateToDisk( |
| 2708 | BlockValidationState &state, |
| 2709 | FlushStateMode mode, |
| 2710 | int nManualPruneHeight) |
| 2711 | { |
| 2712 | LOCK(cs_main); |
| 2713 | assert(this->CanFlushToDisk()); |
| 2714 | std::set<int> setFilesToPrune; |
| 2715 | bool full_flush_completed = false; |
| 2716 | |
| 2717 | [[maybe_unused]] const size_t coins_count{CoinsTip().GetCacheSize()}; |
| 2718 | [[maybe_unused]] const size_t coins_mem_usage{CoinsTip().DynamicMemoryUsage()}; |
| 2719 | |
| 2720 | try { |
| 2721 | { |
| 2722 | bool fFlushForPrune = false; |
| 2723 | |
| 2724 | CoinsCacheSizeState cache_state = GetCoinsCacheSizeState(); |
| 2725 | if (m_blockman.IsPruneMode() && (m_blockman.m_check_for_pruning || nManualPruneHeight > 0) && m_chainman.m_blockman.m_blockfiles_indexed) { |
| 2726 | // make sure we don't prune above any of the prune locks bestblocks |
| 2727 | // pruning is height-based |
| 2728 | int last_prune{m_chain.Height()}; // last height we can prune |
| 2729 | std::optional<std::string> limiting_lock; // prune lock that actually was the limiting factor, only used for logging |
| 2730 | |
| 2731 | for (const auto& prune_lock : m_blockman.m_prune_locks) { |
| 2732 | if (prune_lock.second.height_first == std::numeric_limits<int>::max()) continue; |
| 2733 | // Remove the buffer and one additional block here to get actual height that is outside of the buffer |
| 2734 | const int lock_height{prune_lock.second.height_first - PRUNE_LOCK_BUFFER - 1}; |
| 2735 | last_prune = std::max(1, std::min(last_prune, lock_height)); |
| 2736 | if (last_prune == lock_height) { |
| 2737 | limiting_lock = prune_lock.first; |
| 2738 | } |
| 2739 | } |
| 2740 | |
| 2741 | if (limiting_lock) { |
| 2742 | LogDebug(BCLog::PRUNE, "%s limited pruning to height %d\n", limiting_lock.value(), last_prune); |
| 2743 | } |
| 2744 | |
| 2745 | if (nManualPruneHeight > 0) { |
| 2746 | LOG_TIME_MILLIS_WITH_CATEGORY("find files to prune (manual)", BCLog::BENCH); |
| 2747 | |
| 2748 | m_blockman.FindFilesToPruneManual( |
| 2749 | setFilesToPrune, |
| 2750 | std::min(last_prune, nManualPruneHeight), |
| 2751 | *this); |
| 2752 | } else { |
| 2753 | LOG_TIME_MILLIS_WITH_CATEGORY("find files to prune", BCLog::BENCH); |
| 2754 | |
| 2755 | m_blockman.FindFilesToPrune(setFilesToPrune, last_prune, *this, m_chainman); |
| 2756 | m_blockman.m_check_for_pruning = false; |
| 2757 | } |
| 2758 | if (!setFilesToPrune.empty()) { |
| 2759 | fFlushForPrune = true; |
| 2760 | if (!m_blockman.m_have_pruned) { |
| 2761 | m_blockman.m_block_tree_db->WriteFlag("prunedblockfiles", true); |
| 2762 | m_blockman.m_have_pruned = true; |
| 2763 | } |
| 2764 | } |