diff --git a/include/xrpl/nodestore/DatabaseRotating.h b/include/xrpl/nodestore/DatabaseRotating.h index a35a752c69..5381b5c435 100644 --- a/include/xrpl/nodestore/DatabaseRotating.h +++ b/include/xrpl/nodestore/DatabaseRotating.h @@ -42,15 +42,16 @@ public: std::function const& f) = 0; - /** Marks an online-delete rotation as in progress (or completed). - - While in flight, a read served by the archive backend is copied - forward into the writable backend even for ordinary - (duplicate == false) fetches: the archive is about to be deleted, - and a node body canonicalized into caches during the rotation - window would otherwise survive only in RAM once the archive is - dropped. - */ + /** + * Marks an online-delete rotation as in progress (or completed). + * + * While in flight, a read served by the archive backend is copied + * forward into the writable backend even for ordinary + * (duplicate == false) fetches: the archive is about to be deleted, + * and a node body canonicalized into caches during the rotation + * window would otherwise survive only in RAM once the archive is + * dropped. + */ virtual void setRotationInFlight(bool inFlight) = 0; }; diff --git a/src/libxrpl/nodestore/DatabaseRotatingImp.cpp b/src/libxrpl/nodestore/DatabaseRotatingImp.cpp index c83d79e20e..fd1f3caccc 100644 --- a/src/libxrpl/nodestore/DatabaseRotatingImp.cpp +++ b/src/libxrpl/nodestore/DatabaseRotatingImp.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -64,7 +65,7 @@ DatabaseRotatingImp::rotate( writableBackend_ = std::move(newBackend); - copyForwards = copyForwardCount_.exchange(0, std::memory_order_acq_rel); + copyForwards = copyForwardCount_.exchange(0, std::memory_order_relaxed); } if (copyForwards > 0) @@ -203,13 +204,22 @@ DatabaseRotatingImp::fetchNodeObject( writable = writableBackend_; } - if (!duplicate) + // Update writable backend with data from the archive backend. + // While a rotation is in flight, ordinary (duplicate == false) + // reads served by the archive are copied forward too: the + // archive is about to be deleted, and a body canonicalized + // into the cache after the freshen getKeys() snapshot would + // otherwise survive only in RAM once the archive is dropped. + if (duplicate || rotationInFlight_.load(std::memory_order_acquire)) { - JLOG(j_.warn()) << "Rotating: copy node for ledger " << ledgerSeq - << " from archive to writable backend: " << hash; - ++copyForwardCount_; + if (!duplicate) + { + JLOG(j_.warn()) << "Rotating: copy node for ledger " << ledgerSeq + << " from archive to writable backend: " << hash; + copyForwardCount_.fetch_add(1, std::memory_order_relaxed); + } + writable->store(nodeObject); } - writable->store(nodeObject); } } } diff --git a/src/xrpld/app/misc/SHAMapStoreImp.cpp b/src/xrpld/app/misc/SHAMapStoreImp.cpp index 25fd065f22..e00e5f794a 100644 --- a/src/xrpld/app/misc/SHAMapStoreImp.cpp +++ b/src/xrpld/app/misc/SHAMapStoreImp.cpp @@ -270,6 +270,7 @@ SHAMapStoreImp::copyNode(std::uint64_t& nodeCount, SHAMapTreeNode const& node) node.getHash().asUInt256(), 0, NodeStore::FetchType::Synchronous, true); if (!obj) { + XRPL_ASSERT(node.cowid() == 0, "SHAMapStoreImp::copyNode : rescued node must be clean"); // Reachable from the validated state map in memory, but present in // neither backend: its only on-disk copy lived in a backend removed by // an earlier rotation, and it was never rewritten because it is clean