diff --git a/src/ripple/app/misc/SHAMapStoreImp.cpp b/src/ripple/app/misc/SHAMapStoreImp.cpp index 46fdeeac019..3c9ccb94235 100644 --- a/src/ripple/app/misc/SHAMapStoreImp.cpp +++ b/src/ripple/app/misc/SHAMapStoreImp.cpp @@ -426,22 +426,22 @@ SHAMapStoreImp::run() default:; } - std::string nextArchiveDir = - dbRotating_->getWritableBackend()->getName(); lastRotated_ = validatedSeq; - std::shared_ptr oldBackend; - { - std::lock_guard lock(dbRotating_->peekMutex()); - state_db_.setState(SavedState{ - newBackend->getName(), nextArchiveDir, lastRotated_}); - clearCaches(validatedSeq); - oldBackend = - dbRotating_->rotateBackends(std::move(newBackend), lock); - } - JLOG(journal_.warn()) << "finished rotation " << validatedSeq; + dbRotating_->rotateWithLock( + [&](std::string const& writableBackendName) { + SavedState savedState; + savedState.writableDb = newBackend->getName(); + savedState.archiveDb = writableBackendName; + savedState.lastRotated = lastRotated_; + state_db_.setState(savedState); - oldBackend->setDeletePath(); + clearCaches(validatedSeq); + + return std::move(newBackend); + }); + + JLOG(journal_.warn()) << "finished rotation " << validatedSeq; } } } diff --git a/src/ripple/nodestore/DatabaseRotating.h b/src/ripple/nodestore/DatabaseRotating.h index caf5a9c4a9c..b1feb257095 100644 --- a/src/ripple/nodestore/DatabaseRotating.h +++ b/src/ripple/nodestore/DatabaseRotating.h @@ -47,16 +47,13 @@ class DatabaseRotating : public Database virtual TaggedCache const& getPositiveCache() = 0; - virtual std::mutex& - peekMutex() const = 0; + /** Rotates the backends. - virtual std::shared_ptr const& - getWritableBackend() const = 0; - - virtual std::shared_ptr - rotateBackends( - std::shared_ptr newBackend, - std::lock_guard const&) = 0; + @param f A function executed before the rotation and under the same lock + */ + virtual void + rotateWithLock(std::function( + std::string const& writableBackendName)> const& f) = 0; }; } // namespace NodeStore diff --git a/src/ripple/nodestore/impl/DatabaseRotatingImp.cpp b/src/ripple/nodestore/impl/DatabaseRotatingImp.cpp index f09229efde3..9b9f966ae52 100644 --- a/src/ripple/nodestore/impl/DatabaseRotatingImp.cpp +++ b/src/ripple/nodestore/impl/DatabaseRotatingImp.cpp @@ -55,15 +55,54 @@ DatabaseRotatingImp::DatabaseRotatingImp( setParent(parent); } -std::shared_ptr -DatabaseRotatingImp::rotateBackends( - std::shared_ptr newBackend, - std::lock_guard const&) +void +DatabaseRotatingImp::rotateWithLock( + std::function( + std::string const& writableBackendName)> const& f) { - auto oldBackend{std::move(archiveBackend_)}; + std::lock_guard lock(mutex_); + + auto newBackend = f(writableBackend_->getName()); + archiveBackend_->setDeletePath(); archiveBackend_ = std::move(writableBackend_); writableBackend_ = std::move(newBackend); - return oldBackend; +} + +std::string +DatabaseRotatingImp::getName() const +{ + std::lock_guard lock(mutex_); + return writableBackend_->getName(); +} + +std::int32_t +DatabaseRotatingImp::getWriteLoad() const +{ + std::lock_guard lock(mutex_); + return writableBackend_->getWriteLoad(); +} + +void +DatabaseRotatingImp::import(Database& source) +{ + auto const backend = [&] { + std::lock_guard lock(mutex_); + return writableBackend_; + }(); + + importInternal(*backend, source); +} + +bool +DatabaseRotatingImp::storeLedger(std::shared_ptr const& srcLedger) +{ + auto const backend = [&] { + std::lock_guard lock(mutex_); + return writableBackend_; + }(); + + return Database::storeLedger( + *srcLedger, backend, pCache_, nCache_, nullptr); } void @@ -75,7 +114,13 @@ DatabaseRotatingImp::store( { auto nObj = NodeObject::createObject(type, std::move(data), hash); pCache_->canonicalize_replace_cache(hash, nObj); - getWritableBackend()->store(nObj); + + auto const backend = [&] { + std::lock_guard lock(mutex_); + return writableBackend_; + }(); + backend->store(nObj); + nCache_->erase(hash); storeStats(nObj->getData().size()); } @@ -90,6 +135,7 @@ DatabaseRotatingImp::asyncFetch( object = pCache_->fetch(hash); if (object || nCache_->touch_if_exists(hash)) return true; + // Otherwise post a read Database::asyncFetch(hash, seq, pCache_, nCache_); return false; @@ -114,19 +160,48 @@ DatabaseRotatingImp::sweep() std::shared_ptr DatabaseRotatingImp::fetchFrom(uint256 const& hash, std::uint32_t seq) { - Backends b = getBackends(); - auto nObj = fetchInternal(hash, b.writableBackend); + auto [writable, archive] = [&] { + std::lock_guard lock(mutex_); + return std::make_pair(writableBackend_, archiveBackend_); + }(); + + // Try to fetch from the writable backend + auto nObj = fetchInternal(hash, writable); if (!nObj) { - nObj = fetchInternal(hash, b.archiveBackend); + // Otherwise try to fetch from the archive backend + nObj = fetchInternal(hash, archive); if (nObj) { - getWritableBackend()->store(nObj); + { + // Refresh the writable backend pointer + std::lock_guard lock(mutex_); + writable = writableBackend_; + } + + // Update writable backend with data from the archive backend + writable->store(nObj); nCache_->erase(hash); } } return nObj; } +void +DatabaseRotatingImp::for_each( + std::function)> f) +{ + auto [writable, archive] = [&] { + std::lock_guard lock(mutex_); + return std::make_pair(writableBackend_, archiveBackend_); + }(); + + // Iterate the writable backend + writable->for_each(f); + + // Iterate the archive backend + archive->for_each(f); +} + } // namespace NodeStore } // namespace ripple diff --git a/src/ripple/nodestore/impl/DatabaseRotatingImp.h b/src/ripple/nodestore/impl/DatabaseRotatingImp.h index 8a29d117a2b..ea6c92567ef 100644 --- a/src/ripple/nodestore/impl/DatabaseRotatingImp.h +++ b/src/ripple/nodestore/impl/DatabaseRotatingImp.h @@ -49,41 +49,19 @@ class DatabaseRotatingImp : public DatabaseRotating stopThreads(); } - std::shared_ptr const& - getWritableBackend() const override - { - std::lock_guard lock(rotateMutex_); - return writableBackend_; - } - - std::shared_ptr - rotateBackends( - std::shared_ptr newBackend, - std::lock_guard const&) override; - - std::mutex& - peekMutex() const override - { - return rotateMutex_; - } + void + rotateWithLock( + std::function( + std::string const& writableBackendName)> const& f) override; std::string - getName() const override - { - return getWritableBackend()->getName(); - } + getName() const override; std::int32_t - getWriteLoad() const override - { - return getWritableBackend()->getWriteLoad(); - } + getWriteLoad() const override; void - import(Database& source) override - { - importInternal(*getWritableBackend(), source); - } + import(Database& source) override; void store( @@ -105,11 +83,7 @@ class DatabaseRotatingImp : public DatabaseRotating std::shared_ptr& object) override; bool - storeLedger(std::shared_ptr const& srcLedger) override - { - return Database::storeLedger( - *srcLedger, getWritableBackend(), pCache_, nCache_, nullptr); - } + storeLedger(std::shared_ptr const& srcLedger) override; int getDesiredAsyncReadCount(std::uint32_t seq) override @@ -147,31 +121,13 @@ class DatabaseRotatingImp : public DatabaseRotating std::shared_ptr writableBackend_; std::shared_ptr archiveBackend_; - mutable std::mutex rotateMutex_; - - struct Backends - { - std::shared_ptr const& writableBackend; - std::shared_ptr const& archiveBackend; - }; - - Backends - getBackends() const - { - std::lock_guard lock(rotateMutex_); - return Backends{writableBackend_, archiveBackend_}; - } + mutable std::mutex mutex_; std::shared_ptr fetchFrom(uint256 const& hash, std::uint32_t seq) override; void - for_each(std::function)> f) override - { - Backends b = getBackends(); - b.archiveBackend->for_each(f); - b.writableBackend->for_each(f); - } + for_each(std::function)> f) override; }; } // namespace NodeStore