diff --git a/src/ripple/app/misc/SHAMapStoreImp.cpp b/src/ripple/app/misc/SHAMapStoreImp.cpp index d5cb07792..aa46cdf2d 100644 --- a/src/ripple/app/misc/SHAMapStoreImp.cpp +++ b/src/ripple/app/misc/SHAMapStoreImp.cpp @@ -127,6 +127,16 @@ SHAMapStoreImp::SHAMapStoreImp( "online_delete info from config"); } + if ((!app_.config().section(SECTION_RELATIONAL_DB).empty() && + boost::iequals(get(app.config().section(SECTION_RELATIONAL_DB), "backend"), "memory")) || + (!app_.config().section("node_db").empty() && + boost::iequals(get(app.config().section("node_db"), "type"), "memory"))) + { + Throw( + "Memory does not support online_delete. Remove " + "online_delete info from config. Use [ledger_history] to set a history limit."); + } + // Configuration that affects the behavior of online delete get_if_exists(section, "delete_batch", deleteBatch_); std::uint32_t temp; diff --git a/src/ripple/app/rdb/backend/MemoryDatabase.h b/src/ripple/app/rdb/backend/MemoryDatabase.h index 7a44b9e68..e23d625de 100644 --- a/src/ripple/app/rdb/backend/MemoryDatabase.h +++ b/src/ripple/app/rdb/backend/MemoryDatabase.h @@ -259,9 +259,63 @@ public: ledgers_.emplace(ledger->info().seq, std::move(ledgerData)); ledgerHashToSeq_.emplace(ledger->info().hash, ledger->info().seq); + + // Only perform cleanup when saving the current ledger + if (current) + { + // Calculate the cutoff sequence for old ledgers + auto const cutoffSeq = ledger->info().seq > app_.config().LEDGER_HISTORY + ? ledger->info().seq - app_.config().LEDGER_HISTORY + : 0; + + // Amortized deletion of old ledgers and their associated data + if (cutoffSeq > 0) + { + // We'll delete a batch of old ledgers at a time + const std::size_t BATCH_SIZE = 128; + std::size_t deleted = 0; + + ledgers_.erase_if([&](auto const& item) { + if (deleted >= BATCH_SIZE) + return false; + + if (item.first < cutoffSeq) + { + // Delete associated transactions from the transaction map + item.second.transactions.visit_all( + [this](auto const& txPair) { + transactionMap_.erase(txPair.first); + }); + + // Remove the ledger hash mapping + ledgerHashToSeq_.erase(item.second.info.hash); + + deleted++; + return true; + } + return false; + }); + + // Clean up associated account transactions + if (deleted > 0) + { + accountTxMap_.visit_all([cutoffSeq](auto& item) { + item.second.transactions.erase_if( + [cutoffSeq](auto const& tx) { + return tx.first.first < cutoffSeq; + }); + }); + } + + // update ledger master + app_.getLedgerMaster().clearPriorLedgers(cutoffSeq); + } + } + return true; } + std::optional getLedgerInfoByIndex(LedgerIndex ledgerSeq) override {