From 94b82411fdb5976e8e98b3fe5cf13970c9e741d9 Mon Sep 17 00:00:00 2001 From: Miguel Portilla Date: Tue, 3 Mar 2020 17:08:31 -0500 Subject: [PATCH] [FOLD] Address ximinez's feedback --- src/ripple/app/ledger/impl/InboundLedger.cpp | 2 +- src/ripple/app/ledger/impl/LedgerMaster.cpp | 6 +- src/ripple/nodestore/Database.h | 6 +- src/ripple/nodestore/impl/Database.cpp | 4 +- .../nodestore/impl/DatabaseShardImp.cpp | 173 +++++++++--------- src/ripple/nodestore/impl/DatabaseShardImp.h | 11 +- src/ripple/nodestore/impl/Shard.cpp | 40 ++-- src/ripple/nodestore/impl/Shard.h | 13 +- src/ripple/overlay/impl/PeerImp.cpp | 15 +- src/test/basics/RangeSet_test.cpp | 3 + src/test/nodestore/Database_test.cpp | 4 +- src/test/nodestore/TestBase.h | 2 +- 12 files changed, 149 insertions(+), 130 deletions(-) diff --git a/src/ripple/app/ledger/impl/InboundLedger.cpp b/src/ripple/app/ledger/impl/InboundLedger.cpp index 266695aaf56..db5465593dc 100644 --- a/src/ripple/app/ledger/impl/InboundLedger.cpp +++ b/src/ripple/app/ledger/impl/InboundLedger.cpp @@ -110,7 +110,7 @@ InboundLedger::init(ScopedLockType& collectionLock) if (mFailed) return; } - else if (shardStore && mSeq >= shardStore->earliestSeq()) + else if (shardStore && mSeq >= shardStore->earliestLedgerSeq()) { if (auto l = shardStore->fetchLedger(mHash, mSeq)) { diff --git a/src/ripple/app/ledger/impl/LedgerMaster.cpp b/src/ripple/app/ledger/impl/LedgerMaster.cpp index ddc8f507a74..435a7786262 100644 --- a/src/ripple/app/ledger/impl/LedgerMaster.cpp +++ b/src/ripple/app/ledger/impl/LedgerMaster.cpp @@ -1741,7 +1741,7 @@ LedgerMaster::fetchForHistory( *hash, missing, reason); if (!ledger && missing != fetch_seq_ && - missing > app_.getNodeStore().earliestSeq()) + missing > app_.getNodeStore().earliestLedgerSeq()) { JLOG(m_journal.trace()) << "fetchForHistory want fetch pack " << missing; @@ -1806,7 +1806,7 @@ LedgerMaster::fetchForHistory( else // Do not fetch ledger sequences lower // than the earliest ledger sequence - fetchSz = app_.getNodeStore().earliestSeq(); + fetchSz = app_.getNodeStore().earliestLedgerSeq(); fetchSz = missing >= fetchSz ? std::min(ledger_fetch_size_, (missing - fetchSz) + 1) : 0; try @@ -1866,7 +1866,7 @@ void LedgerMaster::doAdvance (std::unique_lock& sl) std::lock_guard sll(mCompleteLock); missing = prevMissing(mCompleteLedgers, mPubLedger->info().seq, - app_.getNodeStore().earliestSeq()); + app_.getNodeStore().earliestLedgerSeq()); } if (missing) { diff --git a/src/ripple/nodestore/Database.h b/src/ripple/nodestore/Database.h index 57459aabf06..b637e480691 100644 --- a/src/ripple/nodestore/Database.h +++ b/src/ripple/nodestore/Database.h @@ -214,9 +214,9 @@ class Database : public Stoppable /** @return The earliest ledger sequence allowed */ std::uint32_t - earliestSeq() const + earliestLedgerSeq() const { - return earliestSeq_; + return earliestLedgerSeq_; } protected: @@ -285,7 +285,7 @@ class Database : public Stoppable // The default is 32570 to match the XRP ledger network's earliest // allowed sequence. Alternate networks may set this value. - std::uint32_t const earliestSeq_; + std::uint32_t const earliestLedgerSeq_; virtual std::shared_ptr diff --git a/src/ripple/nodestore/impl/Database.cpp b/src/ripple/nodestore/impl/Database.cpp index 5c760f6e1b7..3a377cbd8e6 100644 --- a/src/ripple/nodestore/impl/Database.cpp +++ b/src/ripple/nodestore/impl/Database.cpp @@ -36,12 +36,12 @@ Database::Database( : Stoppable(name, parent.getRoot()) , j_(journal) , scheduler_(scheduler) - , earliestSeq_(get( + , earliestLedgerSeq_(get( config, "earliest_seq", XRP_LEDGER_EARLIEST_SEQ)) { - if (earliestSeq_ < 1) + if (earliestLedgerSeq_ < 1) Throw("Invalid earliest_seq"); while (readThreads-- > 0) diff --git a/src/ripple/nodestore/impl/DatabaseShardImp.cpp b/src/ripple/nodestore/impl/DatabaseShardImp.cpp index 18ec124f881..dddbf48599b 100644 --- a/src/ripple/nodestore/impl/DatabaseShardImp.cpp +++ b/src/ripple/nodestore/impl/DatabaseShardImp.cpp @@ -52,7 +52,7 @@ DatabaseShardImp::DatabaseShardImp( , app_(app) , parent_(parent) , taskQueue_(std::make_unique()) - , earliestShardIndex_(seqToShardIndex(earliestSeq())) + , earliestShardIndex_(seqToShardIndex(earliestLedgerSeq())) , avgShardFileSz_(ledgersPerShard_ * kilobytes(192)) { } @@ -103,7 +103,7 @@ DatabaseShardImp::init() "earliest_seq", seq2) && seq != seq2) { - return fail("and [" + ConfigSection::shardDatabase() + + return fail("and [" + ConfigSection::nodeDatabase() + "] both define 'earliest_seq'"); } } @@ -340,7 +340,7 @@ DatabaseShardImp::prepareShard(std::uint32_t shardIndex) auto seqCheck = [&](std::uint32_t seq) { // seq will be greater than zero if valid - if (seq > earliestSeq() && shardIndex >= seqToShardIndex(seq)) + if (seq > earliestLedgerSeq() && shardIndex >= seqToShardIndex(seq)) return fail("has an invalid index"); return true; }; @@ -607,33 +607,7 @@ DatabaseShardImp::setStored(std::shared_ptr const& ledger) } } - if (!shard->store(ledger)) - return; - - auto const complete {shard->isBackendComplete()}; - { - std::lock_guard lock(mutex_); - if (complete) - { - if (auto const it {shards_.find(shardIndex)}; it != shards_.end()) - { - if (shardIndex == acquireIndex_) - acquireIndex_ = 0; - - if (it->second.state != ShardInfo::State::finalize) - finalizeShard(it->second, false, lock); - } - else - { - JLOG(j_.debug()) << - "shard " << shardIndex << - " is no longer being acquired"; - return; - } - } - } - - setFileStats(); + storeLedgerInShard(shard, ledger); } std::string @@ -648,7 +622,7 @@ DatabaseShardImp::getCompleteShards() void DatabaseShardImp::validate() { - std::vector> wptrShards; + std::vector> shards; { std::lock_guard lock(mutex_); assert(init_); @@ -656,17 +630,17 @@ DatabaseShardImp::validate() // Only shards with a state of final should be validated for (auto& e : shards_) if (e.second.state == ShardInfo::State::final) - wptrShards.push_back(e.second.shard); + shards.push_back(e.second.shard); - if (wptrShards.empty()) + if (shards.empty()) return; JLOG(j_.debug()) << "Validating shards " << status_; } - for (auto const& wptr : wptrShards) + for (auto const& e : shards) { - if (auto shard {wptr.lock()}; shard) + if (auto shard {e.lock()}; shard) shard->finalize(true); } @@ -710,7 +684,7 @@ DatabaseShardImp::import(Database& source) std::shared_ptr ledger; std::uint32_t seq; std::tie(ledger, seq, std::ignore) = loadLedgerHelper( - "WHERE LedgerSeq >= " + std::to_string(earliestSeq()) + + "WHERE LedgerSeq >= " + std::to_string(earliestLedgerSeq()) + " order by LedgerSeq " + (ascendSort ? "asc" : "desc") + " limit 1", app_, false); if (!ledger || seq == 0) @@ -985,9 +959,6 @@ DatabaseShardImp::asyncFetch( bool DatabaseShardImp::copyLedger(std::shared_ptr const& srcLedger) { - if (isStopping()) - return false; - auto const seq {srcLedger->info().seq}; auto const shardIndex {seqToShardIndex(seq)}; std::shared_ptr shard; @@ -1023,34 +994,7 @@ DatabaseShardImp::copyLedger(std::shared_ptr const& srcLedger) if (!Database::copyLedger(*srcLedger, backend, pCache, nCache, lastStored)) return false; - if (!shard->store(srcLedger)) - return false; - - auto const complete {shard->isBackendComplete()}; - { - std::lock_guard lock(mutex_); - if (complete) - { - if (auto const it {shards_.find(shardIndex)}; it != shards_.end()) - { - if (shardIndex == acquireIndex_) - acquireIndex_ = 0; - - if (it->second.state != ShardInfo::State::finalize) - finalizeShard(it->second, false, lock); - } - else - { - JLOG(j_.debug()) << - "shard " << shardIndex << - " is no longer being acquired"; - return false; - } - } - } - - setFileStats(); - return true; + return storeLedgerInShard(shard, srcLedger); } int @@ -1096,7 +1040,7 @@ DatabaseShardImp::getCacheHitRate() void DatabaseShardImp::sweep() { - std::vector> wptrShards; + std::vector> shards; { std::lock_guard lock(mutex_); assert(init_); @@ -1105,13 +1049,13 @@ DatabaseShardImp::sweep() if (e.second.state == ShardInfo::State::final || e.second.state == ShardInfo::State::acquire) { - wptrShards.push_back(e.second.shard); + shards.push_back(e.second.shard); } } - for (auto const& wptr : wptrShards) + for (auto const& e : shards) { - if (auto shard {wptr.lock()}; shard) + if (auto shard {e.lock()}; shard) shard->sweep(); } } @@ -1143,6 +1087,8 @@ DatabaseShardImp::findAcquireIndex( std::uint32_t validLedgerSeq, std::lock_guard&) { + assert(validLedgerSeq >= earliestLedgerSeq()); + auto const maxShardIndex {[this, validLedgerSeq]() { auto shardIndex {seqToShardIndex(validLedgerSeq)}; @@ -1150,18 +1096,19 @@ DatabaseShardImp::findAcquireIndex( --shardIndex; return shardIndex; }()}; + auto const maxNumShards {maxShardIndex - earliestShardIndex() + 1}; // Check if the shard store has all shards - if (shards_.size() >= maxShardIndex) + if (shards_.size() >= maxNumShards) return boost::none; if (maxShardIndex < 1024 || - static_cast(shards_.size()) / maxShardIndex > 0.5f) + static_cast(shards_.size()) / maxNumShards > 0.5f) { // Small or mostly full index space to sample // Find the available indexes and select one at random std::vector available; - available.reserve(maxShardIndex - shards_.size() + 1); + available.reserve(maxNumShards - shards_.size()); for (auto shardIndex = earliestShardIndex(); shardIndex <= maxShardIndex; @@ -1209,7 +1156,7 @@ DatabaseShardImp::finalizeShard( auto const shardIndex {shardInfo.shard->index()}; shardInfo.state = ShardInfo::State::finalize; - taskQueue_->addTask([this, shardIndex, writeSQLite]() mutable + taskQueue_->addTask([this, shardIndex, writeSQLite]() { if (isStopping()) return; @@ -1232,13 +1179,13 @@ DatabaseShardImp::finalizeShard( if (isStopping()) return; - // Finalize failed, remove shard + // Bad shard, remove it { std::lock_guard lock(mutex_); shards_.erase(shardIndex); + updateStatus(lock); - using namespace boost::filesystem; - path const dir {shard->getDir()}; + boost::filesystem::path const dir {shard->getDir()}; shard.reset(); try { @@ -1246,10 +1193,9 @@ DatabaseShardImp::finalizeShard( } catch (std::exception const& e) { - JLOG(j_.error()) << "exception " << e.what(); + JLOG(j_.error()) << + "exception " << e.what() << " in function " << __func__; } - - updateStatus(lock); } setFileStats(); @@ -1289,7 +1235,7 @@ DatabaseShardImp::finalizeShard( void DatabaseShardImp::setFileStats() { - std::vector> wptrShards; + std::vector> shards; { std::lock_guard lock(mutex_); assert(init_); @@ -1303,15 +1249,15 @@ DatabaseShardImp::setFileStats() for (auto const& e : shards_) if (e.second.shard) - wptrShards.push_back(e.second.shard); + shards.push_back(e.second.shard); } std::uint64_t sumSz {0}; std::uint32_t sumFd {0}; std::uint32_t numShards {0}; - for (auto const& wptr : wptrShards) + for (auto const& e : shards) { - if (auto shard {wptr.lock()}; shard) + if (auto shard {e.lock()}; shard) { auto[sz, fd] = shard->fileInfo(); sumSz += sz; @@ -1392,6 +1338,63 @@ DatabaseShardImp::available() const } } +bool +DatabaseShardImp::storeLedgerInShard( + std::shared_ptr& shard, + std::shared_ptr const& ledger) +{ + bool result {true}; + + if (!shard->store(ledger)) + { + // Shard may be corrupt, remove it + std::lock_guard lock(mutex_); + + shards_.erase(shard->index()); + if (shard->index() == acquireIndex_) + acquireIndex_ = 0; + + updateStatus(lock); + + boost::filesystem::path const dir {shard->getDir()}; + shard.reset(); + try + { + remove_all(dir); + } + catch (std::exception const& e) + { + JLOG(j_.error()) << + "exception " << e.what() << " in function " << __func__; + } + + result = false; + } + else if (shard->isBackendComplete()) + { + std::lock_guard lock(mutex_); + + if (auto const it {shards_.find(shard->index())}; + it != shards_.end()) + { + if (shard->index() == acquireIndex_) + acquireIndex_ = 0; + + if (it->second.state != ShardInfo::State::finalize) + finalizeShard(it->second, false, lock); + } + else + { + JLOG(j_.debug()) << + "shard " << shard->index() << + " is no longer being acquired"; + } + } + + setFileStats(); + return result; +} + //------------------------------------------------------------------------------ std::unique_ptr diff --git a/src/ripple/nodestore/impl/DatabaseShardImp.h b/src/ripple/nodestore/impl/DatabaseShardImp.h index d279d92bf3a..00094b61313 100644 --- a/src/ripple/nodestore/impl/DatabaseShardImp.h +++ b/src/ripple/nodestore/impl/DatabaseShardImp.h @@ -27,8 +27,6 @@ namespace ripple { namespace NodeStore { -class TaskQueue; - class DatabaseShardImp : public DatabaseShard { public: @@ -95,7 +93,7 @@ class DatabaseShardImp : public DatabaseShard std::uint32_t seqToShardIndex(std::uint32_t seq) const override { - assert(seq >= earliestSeq()); + assert(seq >= earliestLedgerSeq()); return NodeStore::seqToShardIndex(seq, ledgersPerShard_); } @@ -104,7 +102,7 @@ class DatabaseShardImp : public DatabaseShard { assert(shardIndex >= earliestShardIndex_); if (shardIndex <= earliestShardIndex_) - return earliestSeq(); + return earliestLedgerSeq(); return 1 + (shardIndex * ledgersPerShard_); } @@ -282,6 +280,11 @@ class DatabaseShardImp : public DatabaseShard // Returns available storage space std::uint64_t available() const; + + bool + storeLedgerInShard( + std::shared_ptr& shard, + std::shared_ptr const& ledger); }; } // NodeStore diff --git a/src/ripple/nodestore/impl/Shard.cpp b/src/ripple/nodestore/impl/Shard.cpp index 20c3b821ef3..6fcc5455ad2 100644 --- a/src/ripple/nodestore/impl/Shard.cpp +++ b/src/ripple/nodestore/impl/Shard.cpp @@ -202,9 +202,10 @@ Shard::open(Scheduler& scheduler, nudb::context& ctx) } setBackendCache(lock); - if (!initSQLite(lock) || !setFileStats(lock)) + if (!initSQLite(lock)) return fail({}); + setFileStats(lock); return true; } @@ -233,7 +234,7 @@ Shard::store(std::shared_ptr const& ledger) "shard " << index_ << " has ledger sequence " << seq << " already stored"; - return false; + return true; } storedSeqs_.insert(seq); @@ -244,13 +245,13 @@ Shard::store(std::shared_ptr const& ledger) if (boost::icl::length(storedSeqs_) >= maxLedgers_) { + if (!initSQLite(lock)) + return false; + storedSeqs_.clear(); lastStored_.reset(); backendComplete_ = true; setBackendCache(lock); - - if (!initSQLite(lock) || !setFileStats(lock)) - return false; } JLOG(j_.debug()) << @@ -258,6 +259,7 @@ Shard::store(std::shared_ptr const& ledger) " stored ledger sequence " << seq << (backendComplete_ ? " . All ledgers stored" : ""); + setFileStats(lock); return true; } @@ -455,11 +457,10 @@ Shard::finalize(const bool writeSQLite) convert(sociBlob, s); lock.lock(); - if (!from_string(storedSeqs_, s)) - return fail("invalid StoredLedgerSeqs"); - - if (boost::icl::first(storedSeqs_) != firstSeq_ || - boost::icl::last(storedSeqs_) != lastSeq_) + if (!from_string(storedSeqs_, s) || + boost::icl::first(storedSeqs_) != firstSeq_ || + boost::icl::last(storedSeqs_) != lastSeq_ || + storedSeqs_.size() != maxLedgers_) { return fail("invalid StoredLedgerSeqs"); } @@ -580,13 +581,18 @@ Shard::finalize(const bool writeSQLite) acquireSQLiteDB_.reset(); remove_all(dir_ / AcquireDBName); - return initSQLite(lock) && setFileStats(lock); + if (!initSQLite(lock)) + return false; + + setFileStats(lock); } catch (std::exception const& e) { return fail(std::string("exception ") + e.what() + " in function " + __func__); } + + return true; } void @@ -880,7 +886,7 @@ Shard::storeSQLite( return true; } -bool +void Shard::setFileStats(std::lock_guard const&) { fileSz_ = 0; @@ -899,19 +905,17 @@ Shard::setFileStats(std::lock_guard const&) } catch (std::exception const& e) { - JLOG(j_.fatal()) << + JLOG(j_.error()) << "shard " << index_ << " exception " << e.what() << " in function " << __func__; - return false; } - return true; } bool Shard::valLedger( std::shared_ptr const& ledger, - std::shared_ptr const& next) + std::shared_ptr const& next) const { auto fail = [j = j_, index = index_, &ledger](std::string const& msg) { @@ -987,10 +991,10 @@ Shard::valLedger( } return true; -}; +} std::shared_ptr -Shard::valFetch(uint256 const& hash) +Shard::valFetch(uint256 const& hash) const { std::shared_ptr nObj; auto fail = [j = j_, index = index_, &hash, &nObj](std::string const& msg) diff --git a/src/ripple/nodestore/impl/Shard.h b/src/ripple/nodestore/impl/Shard.h index 223d11b3ee6..1a3fc43f3c0 100644 --- a/src/ripple/nodestore/impl/Shard.h +++ b/src/ripple/nodestore/impl/Shard.h @@ -99,6 +99,9 @@ class Shard final std::shared_ptr nCache() const; + /** Returns a pair where the first item describes the storage space + utilized and the second item is the number of file descriptors required. + */ std::pair fileInfo() const; @@ -128,7 +131,7 @@ class Shard final private: // Current shard version - static constexpr std::uint32_t version_ {1}; + static constexpr std::uint32_t version_ {2}; // The finalKey_ is a hard coded value of zero. It is used to store // finalizing shard data to the backend. The data contains a version, @@ -184,6 +187,8 @@ class Shard final bool backendComplete_ {false}; // Tracks ledger sequences stored in the backend when building a shard + // Once the backend has stored all ledgers pertaining to the shard, + // this will be empty RangeSet storedSeqs_; // Used as an optimization for visitDifferences @@ -218,18 +223,18 @@ class Shard final // Set storage and file descriptor usage stats // Lock over mutex_ required - bool + void setFileStats(std::lock_guard const& lock); // Validate this ledger by walking its SHAMaps and verifying Merkle trees bool valLedger( std::shared_ptr const& ledger, - std::shared_ptr const& next); + std::shared_ptr const& next) const; // Fetches from backend and log errors based on status codes std::shared_ptr - valFetch(uint256 const& hash); + valFetch(uint256 const& hash) const; }; } // namespace NodeStore diff --git a/src/ripple/overlay/impl/PeerImp.cpp b/src/ripple/overlay/impl/PeerImp.cpp index ff1cb451c6f..7908914e110 100644 --- a/src/ripple/overlay/impl/PeerImp.cpp +++ b/src/ripple/overlay/impl/PeerImp.cpp @@ -431,7 +431,7 @@ PeerImp::hasLedger (uint256 const& hash, std::uint32_t seq) const return true; } - return seq >= app_.getNodeStore().earliestSeq() && + return seq >= app_.getNodeStore().earliestLedgerSeq() && hasShard(NodeStore::seqToShardIndex(seq)); } @@ -1270,14 +1270,15 @@ PeerImp::onMessage(std::shared_ptr const& m) if (auto shardStore = app_.getShardStore()) { earliestShard = shardStore->earliestShardIndex(); - if (curLedgerSeq >= shardStore->earliestSeq()) + if (curLedgerSeq >= shardStore->earliestLedgerSeq()) latestShard = shardStore->seqToShardIndex(curLedgerSeq); } else { - auto const earliestSeq {app_.getNodeStore().earliestSeq()}; - earliestShard = NodeStore::seqToShardIndex(earliestSeq); - if (curLedgerSeq >= earliestSeq) + auto const earliestLedgerSeq { + app_.getNodeStore().earliestLedgerSeq()}; + earliestShard = NodeStore::seqToShardIndex(earliestLedgerSeq); + if (curLedgerSeq >= earliestLedgerSeq) latestShard = NodeStore::seqToShardIndex(curLedgerSeq); } } @@ -2223,7 +2224,7 @@ PeerImp::onMessage (std::shared_ptr const& m) { if (auto shardStore = app_.getShardStore()) { - if (seq >= shardStore->earliestSeq()) + if (seq >= shardStore->earliestLedgerSeq()) hObj = shardStore->fetch(hash, seq); } } @@ -2669,7 +2670,7 @@ PeerImp::getLedger (std::shared_ptr const& m) if (auto shardStore = app_.getShardStore()) { auto seq = packet.ledgerseq(); - if (seq >= shardStore->earliestSeq()) + if (seq >= shardStore->earliestLedgerSeq()) ledger = shardStore->fetchLedger(ledgerhash, seq); } } diff --git a/src/test/basics/RangeSet_test.cpp b/src/test/basics/RangeSet_test.cpp index 078daed9030..d46fd4467b7 100644 --- a/src/test/basics/RangeSet_test.cpp +++ b/src/test/basics/RangeSet_test.cpp @@ -116,7 +116,10 @@ class RangeSet_test : public beast::unit_test::suite BEAST_EXPECT(from_string(set, "1,4-6")); BEAST_EXPECT(boost::icl::length(set) == 4); BEAST_EXPECT(boost::icl::first(set) == 1); + BEAST_EXPECT(!boost::icl::contains(set, 2)); + BEAST_EXPECT(!boost::icl::contains(set, 3)); BEAST_EXPECT(boost::icl::contains(set, 4)); + BEAST_EXPECT(boost::icl::contains(set, 5)); BEAST_EXPECT(boost::icl::last(set) == 6); set.clear(); diff --git a/src/test/nodestore/Database_test.cpp b/src/test/nodestore/Database_test.cpp index ae38fd63e42..12d37580518 100644 --- a/src/test/nodestore/Database_test.cpp +++ b/src/test/nodestore/Database_test.cpp @@ -165,7 +165,7 @@ class Database_test : public TestBase std::unique_ptr db = Manager::instance().make_Database( "test", scheduler, 2, parent, nodeParams, journal_); - BEAST_EXPECT(db->earliestSeq() == XRP_LEDGER_EARLIEST_SEQ); + BEAST_EXPECT(db->earliestLedgerSeq() == XRP_LEDGER_EARLIEST_SEQ); } // Set an invalid earliest ledger sequence @@ -190,7 +190,7 @@ class Database_test : public TestBase "test", scheduler, 2, parent, nodeParams, journal_); // Verify database uses the earliest ledger sequence setting - BEAST_EXPECT(db->earliestSeq() == 1); + BEAST_EXPECT(db->earliestLedgerSeq() == 1); } diff --git a/src/test/nodestore/TestBase.h b/src/test/nodestore/TestBase.h index 5343931e72b..e1fd0cfe531 100644 --- a/src/test/nodestore/TestBase.h +++ b/src/test/nodestore/TestBase.h @@ -195,7 +195,7 @@ class TestBase : public beast::unit_test::suite db.store (object->getType (), std::move (data), object->getHash (), - db.earliestSeq()); + db.earliestLedgerSeq()); } }