diff --git a/triedb/pathdb/database.go b/triedb/pathdb/database.go index 36df506b78..9e734b5e1c 100644 --- a/triedb/pathdb/database.go +++ b/triedb/pathdb/database.go @@ -442,7 +442,7 @@ func (db *Database) Close() error { // Release the memory held by clean cache. disk := db.tree.bottom() if disk.frozen != nil { - if err := disk.frozen.flushed(); err != nil { + if err := disk.frozen.waitFlush(); err != nil { return err } } diff --git a/triedb/pathdb/disklayer.go b/triedb/pathdb/disklayer.go index 7239ba7d16..35f609e93a 100644 --- a/triedb/pathdb/disklayer.go +++ b/triedb/pathdb/disklayer.go @@ -140,6 +140,11 @@ func (dl *diskLayer) node(owner common.Hash, path []byte, depth int) ([]byte, co } else { blob = rawdb.ReadStorageTrieNode(dl.db.diskdb, owner, path) } + // Store the resolved data in the clean cache. The background buffer flusher + // may also write to the clean cache concurrently, but two writers cannot + // write the same item with different content. If the item already exists, + // it will be found in the frozen buffer, eliminating the need to check the + // database. if dl.cleans != nil && len(blob) > 0 { dl.cleans.Set(key, blob) cleanWriteMeter.Mark(int64(len(blob))) @@ -208,7 +213,7 @@ func (dl *diskLayer) commit(bottom *diffLayer, force bool) (*diskLayer, error) { if combined.full() || force { // Wait until the previous frozen buffer is fully flushed if dl.frozen != nil { - if err := dl.frozen.flushed(); err != nil { + if err := dl.frozen.waitFlush(); err != nil { return nil, err } } @@ -221,7 +226,7 @@ func (dl *diskLayer) commit(bottom *diffLayer, force bool) (*diskLayer, error) { // Block until the frozen buffer is fully flushed out if the oldest history // surpasses the persisted state ID. if persistedID < oldest { - if err := dl.frozen.flushed(); err != nil { + if err := dl.frozen.waitFlush(); err != nil { return nil, err } } @@ -278,10 +283,12 @@ func (dl *diskLayer) revert(h *history) (*diskLayer, error) { } else { // Block until the frozen buffer is fully flushed if dl.frozen != nil { - if err := dl.frozen.flushed(); err != nil { + if err := dl.frozen.waitFlush(); err != nil { return nil, err } - dl.frozen = nil // unset the frozen buffer + // Unset the frozen buffer if it exists, otherwise these "reverted" + // states will still be accessible after revert in frozen buffer. + dl.frozen = nil } batch := dl.db.diskdb.NewBatch() writeNodes(batch, nodes, dl.cleans) diff --git a/triedb/pathdb/journal.go b/triedb/pathdb/journal.go index 0d4c2025a9..2a73f05fb7 100644 --- a/triedb/pathdb/journal.go +++ b/triedb/pathdb/journal.go @@ -343,7 +343,7 @@ func (db *Database) Journal(root common.Hash) error { } disk := db.tree.bottom() if disk.frozen != nil { - if err := disk.frozen.flushed(); err != nil { + if err := disk.frozen.waitFlush(); err != nil { return err } } diff --git a/triedb/pathdb/layertree.go b/triedb/pathdb/layertree.go index 795ec7917f..5f1677215e 100644 --- a/triedb/pathdb/layertree.go +++ b/triedb/pathdb/layertree.go @@ -133,7 +133,7 @@ func (tree *layerTree) cap(root common.Hash, layers int) error { } // Block until the frozen buffer is fully flushed if base.frozen != nil { - if err := base.frozen.flushed(); err != nil { + if err := base.frozen.waitFlush(); err != nil { return err } } diff --git a/triedb/pathdb/nodebuffer.go b/triedb/pathdb/nodebuffer.go index 8ea64a36ad..2a7136dd22 100644 --- a/triedb/pathdb/nodebuffer.go +++ b/triedb/pathdb/nodebuffer.go @@ -245,12 +245,14 @@ func (b *nodebuffer) flush(db ethdb.KeyValueStore, clean *fastcache.Cache, id ui commitNodesMeter.Mark(int64(nodes)) commitTimeTimer.UpdateSince(start) log.Info("Persisted pathdb nodes", "nodes", nodes, "bytes", common.StorageSize(size), "elapsed", common.PrettyDuration(time.Since(start))) + + // The content in the frozen buffer is kept for consequent state access }() } -// flushed blocks until the buffer is fully flushed and also returns the memorized -// error which occurs within the flushing. -func (b *nodebuffer) flushed() error { +// waitFlush blocks until the buffer has been fully flushed and returns any +// stored errors that occurred during the process. +func (b *nodebuffer) waitFlush() error { <-b.done return b.flushErr }