//------------------------------------------------------------------------------ bool Ledger::walkLedger (beast::Journal j) const { std::vector <SHAMapMissingNode> missingNodes1; std::vector <SHAMapMissingNode> missingNodes2; if (stateMap_->getHash().isZero() && ! info_.accountHash.isZero() && ! stateMap_->fetchRoot (SHAMapHash{info_.accountHash}, nullptr)) { missingNodes1.emplace_back (SHAMapType::STATE, SHAMapHash{info_.accountHash}); } else { stateMap_->walkMap (missingNodes1, 32); } if (!missingNodes1.empty ()) { if (auto stream = j.info()) { stream << missingNodes1.size () << " missing account node(s)"; stream << "First: " << missingNodes1[0]; } } if (txMap_->getHash().isZero() && info_.txHash.isNonZero() && ! txMap_->fetchRoot (SHAMapHash{info_.txHash}, nullptr)) { missingNodes2.emplace_back (SHAMapType::TRANSACTION, SHAMapHash{info_.txHash}); } else { txMap_->walkMap (missingNodes2, 32); } if (!missingNodes2.empty ()) { if (auto stream = j.info()) { stream << missingNodes2.size () << " missing transaction node(s)"; stream << "First: " << missingNodes2[0]; } } return missingNodes1.empty () && missingNodes2.empty (); }
void onStop () override { JLOG (j_.info()) << "Stopping"; { std::lock_guard<std::mutex> lock (mutex_); shouldExit_ = true; wakeup_.notify_one(); } thread_.join(); }
/** Run the ledger cleaner. */ void doLedgerCleaner() { auto shouldExit = [this]() { std::lock_guard<std::mutex> lock(mutex_); return shouldExit_; }; std::shared_ptr<ReadView const> goodLedger; while (! shouldExit()) { LedgerIndex ledgerIndex; LedgerHash ledgerHash; bool doNodes; bool doTxns; while (app_.getFeeTrack().isLoadedLocal()) { JLOG (j_.debug()) << "Waiting for load to subside"; std::this_thread::sleep_for(std::chrono::seconds(5)); if (shouldExit()) return; } { std::lock_guard<std::mutex> lock (mutex_); if ((minRange_ > maxRange_) || (maxRange_ == 0) || (minRange_ == 0)) { minRange_ = maxRange_ = 0; state_ = State::readyToClean; return; } ledgerIndex = maxRange_; doNodes = checkNodes_; doTxns = fixTxns_; } ledgerHash = getHash(ledgerIndex, goodLedger); bool fail = false; if (ledgerHash.isZero()) { JLOG (j_.info()) << "Unable to get hash for ledger " << ledgerIndex; fail = true; } else if (!doLedger(ledgerIndex, ledgerHash, doNodes, doTxns)) { JLOG (j_.info()) << "Failed to process ledger " << ledgerIndex; fail = true; } if (fail) { { std::lock_guard<std::mutex> lock (mutex_); ++failures_; } // Wait for acquiring to catch up to us std::this_thread::sleep_for(std::chrono::seconds(2)); } else { { std::lock_guard<std::mutex> lock (mutex_); if (ledgerIndex == minRange_) ++minRange_; if (ledgerIndex == maxRange_) --maxRange_; failures_ = 0; } // Reduce I/O pressure and wait for acquiring to catch up to us std::this_thread::sleep_for(std::chrono::milliseconds(100)); } } }