/** Process a single ledger @param ledgerIndex The index of the ledger to process. @param ledgerHash The known correct hash of the ledger. @param doNodes Ensure all ledger nodes are in the node db. @param doTxns Reprocess (account) transactions to SQL databases. @return `true` if the ledger was cleaned. */ bool doLedger( LedgerIndex const& ledgerIndex, LedgerHash const& ledgerHash, bool doNodes, bool doTxns) { auto nodeLedger = app_.getInboundLedgers().acquire ( ledgerHash, ledgerIndex, InboundLedger::fcGENERIC); if (!nodeLedger) { JLOG (j_.debug()) << "Ledger " << ledgerIndex << " not available"; app_.getLedgerMaster().clearLedger (ledgerIndex); app_.getInboundLedgers().acquire( ledgerHash, ledgerIndex, InboundLedger::fcGENERIC); return false; } auto dbLedger = loadByIndex(ledgerIndex, app_); if (! dbLedger || (dbLedger->info().hash != ledgerHash) || (dbLedger->info().parentHash != nodeLedger->info().parentHash)) { // Ideally we'd also check for more than one ledger with that index JLOG (j_.debug()) << "Ledger " << ledgerIndex << " mismatches SQL DB"; doTxns = true; } if(! app_.getLedgerMaster().fixIndex(ledgerIndex, ledgerHash)) { JLOG (j_.debug()) << "ledger " << ledgerIndex << " had wrong entry in history"; doTxns = true; } if (doNodes && !nodeLedger->walkLedger(app_.journal ("Ledger"))) { JLOG (j_.debug()) << "Ledger " << ledgerIndex << " is missing nodes"; app_.getLedgerMaster().clearLedger (ledgerIndex); app_.getInboundLedgers().acquire( ledgerHash, ledgerIndex, InboundLedger::fcGENERIC); return false; } if (doTxns && !pendSaveValidated(app_, nodeLedger, true, false)) { JLOG (j_.debug()) << "Failed to save ledger " << ledgerIndex; return false; } return true; }
void saveLedgerAsync (Application& app, std::uint32_t seq) { if (auto l = app.getLedgerMaster().getLedgerBySeq(seq)) pendSaveValidated(app, l, false, false); }