diff --git a/triedb/pathdb/asyncnodebuffer.go b/triedb/pathdb/asyncnodebuffer.go index 00d4be133b..aafa9e8caf 100644 --- a/triedb/pathdb/asyncnodebuffer.go +++ b/triedb/pathdb/asyncnodebuffer.go @@ -194,6 +194,18 @@ func (a *asyncnodebuffer) getSize() (uint64, uint64) { return a.current.size(), a.background.size() } +func (a *asyncnodebuffer) forceFlush(db ethdb.KeyValueStore, freezer ethdb.AncientWriter, clean *fastcache.Cache, id uint64) error { + for { + if atomic.LoadUint64(&a.background.immutable) == 1 { + time.Sleep(time.Duration(DefaultBackgroundFlushInterval) * time.Second) + log.Info("Waiting background memory table flushed into disk for forcing flush node buffer") + continue + } + atomic.StoreUint64(&a.current.immutable, 1) + return a.current.flush(db, freezer, clean, id, true) + } +} + type nodecache struct { *buffer immutable uint64 // The flag equal 1, flush nodes to disk background diff --git a/triedb/pathdb/buffer.go b/triedb/pathdb/buffer.go index a62ab478e0..20198542f8 100644 --- a/triedb/pathdb/buffer.go +++ b/triedb/pathdb/buffer.go @@ -17,6 +17,7 @@ package pathdb import ( + "errors" "fmt" "time" @@ -188,3 +189,7 @@ func (b *buffer) getLayers() uint64 { func (b *buffer) getSize() (uint64, uint64) { return b.size(), 0 } + +func (b *buffer) forceFlush(db ethdb.KeyValueStore, freezer ethdb.AncientWriter, clean *fastcache.Cache, id uint64) error { + return errors.New("unsupported method") +} diff --git a/triedb/pathdb/database_test.go b/triedb/pathdb/database_test.go index f7245ef038..55917428eb 100644 --- a/triedb/pathdb/database_test.go +++ b/triedb/pathdb/database_test.go @@ -520,10 +520,7 @@ func TestDatabaseRecoverable(t *testing.T) { } } -// TODO(joey): fail when using asyncbuffer -// -//nolint:unused -func testDisable(t *testing.T) { +func TestDisable(t *testing.T) { // Redefine the diff layer depth allowance for faster testing. maxDiffLayers = 4 defer func() { @@ -531,6 +528,10 @@ func testDisable(t *testing.T) { }() tester := newTester(t, 0, false, 32) + bottom := tester.db.tree.bottom() + if err := bottom.buffer.forceFlush(tester.db.diskdb, tester.db.freezer, nil, bottom.id); err != nil { + t.Fatalf("Failed to force flush: %v", err) + } defer tester.release() stored := crypto.Keccak256Hash(rawdb.ReadAccountTrieNode(tester.db.diskdb, nil)) diff --git a/triedb/pathdb/disklayer.go b/triedb/pathdb/disklayer.go index d505e7d34f..423c16c71a 100644 --- a/triedb/pathdb/disklayer.go +++ b/triedb/pathdb/disklayer.go @@ -75,6 +75,9 @@ type trienodebuffer interface { // getSize return the trienodebuffer used size. getSize() (uint64, uint64) + + // forceFlush used for asyncnodebuffer unit test + forceFlush(db ethdb.KeyValueStore, freezer ethdb.AncientWriter, clean *fastcache.Cache, id uint64) error } func NewTrieNodeBuffer(sync bool, limit int, nodes *nodeSet, states *stateSet, layers uint64) trienodebuffer {