triedb/pathdb: fix test stall

This commit is contained in:
Gary Rong 2026-03-12 10:58:08 +08:00
parent 4a4c9a27d2
commit 04f16489ee
6 changed files with 25 additions and 15 deletions

View file

@ -105,9 +105,10 @@ type Config struct {
FullValueCheckpoint uint32 // The rate at which trie nodes are encoded in full-value format FullValueCheckpoint uint32 // The rate at which trie nodes are encoded in full-value format
// Testing configurations // Testing configurations
SnapshotNoBuild bool // Flag Whether the state generation is disabled SnapshotNoBuild bool // Flag Whether the state generation is disabled
NoAsyncFlush bool // Flag whether the background buffer flushing is disabled NoAsyncFlush bool // Flag whether the background buffer flushing is disabled
NoAsyncGeneration bool // Flag whether the background generation is disabled NoAsyncGeneration bool // Flag whether the background generation is disabled
NoHistoryIndexDelay bool // Flag whether the history index delay is disabled
} }
// sanitize checks the provided user configurations and changes anything that's // sanitize checks the provided user configurations and changes anything that's

View file

@ -215,14 +215,14 @@ func (db *Database) setHistoryIndexer() {
if db.stateIndexer != nil { if db.stateIndexer != nil {
db.stateIndexer.close() db.stateIndexer.close()
} }
db.stateIndexer = newHistoryIndexer(db.diskdb, db.stateFreezer, db.tree.bottom().stateID(), typeStateHistory) db.stateIndexer = newHistoryIndexer(db.diskdb, db.stateFreezer, db.tree.bottom().stateID(), typeStateHistory, db.config.NoHistoryIndexDelay)
log.Info("Enabled state history indexing") log.Info("Enabled state history indexing")
} }
if db.trienodeFreezer != nil { if db.trienodeFreezer != nil {
if db.trienodeIndexer != nil { if db.trienodeIndexer != nil {
db.trienodeIndexer.close() db.trienodeIndexer.close()
} }
db.trienodeIndexer = newHistoryIndexer(db.diskdb, db.trienodeFreezer, db.tree.bottom().stateID(), typeTrienodeHistory) db.trienodeIndexer = newHistoryIndexer(db.diskdb, db.trienodeFreezer, db.tree.bottom().stateID(), typeTrienodeHistory, db.config.NoHistoryIndexDelay)
log.Info("Enabled trienode history indexing") log.Info("Enabled trienode history indexing")
} }
} }

View file

@ -182,6 +182,7 @@ func newTester(t *testing.T, config *testerConfig) *tester {
WriteBufferSize: config.writeBufferSize(), WriteBufferSize: config.writeBufferSize(),
NoAsyncFlush: true, NoAsyncFlush: true,
JournalDirectory: config.journalDir, JournalDirectory: config.journalDir,
NoHistoryIndexDelay: true,
}, config.isVerkle) }, config.isVerkle)
obj = &tester{ obj = &tester{

View file

@ -367,9 +367,9 @@ type indexIniter struct {
wg sync.WaitGroup wg sync.WaitGroup
} }
func newIndexIniter(disk ethdb.Database, freezer ethdb.AncientStore, typ historyType, lastID uint64) *indexIniter { func newIndexIniter(disk ethdb.Database, freezer ethdb.AncientStore, typ historyType, lastID uint64, noWait bool) *indexIniter {
initer := &indexIniter{ initer := &indexIniter{
state: newIniterState(disk), state: newIniterState(disk, noWait),
disk: disk, disk: disk,
freezer: freezer, freezer: freezer,
interrupt: make(chan *interruptSignal), interrupt: make(chan *interruptSignal),
@ -441,14 +441,17 @@ func (i *indexIniter) run(recover bool) {
// checkDone reports whether indexing has completed for all histories. // checkDone reports whether indexing has completed for all histories.
checkDone = func() bool { checkDone = func() bool {
return i.indexed.Load() == i.last.Load() metadata := loadIndexMetadata(i.disk, i.typ)
return metadata != nil && metadata.Last == i.last.Load()
} }
// canExit reports whether the initial indexing phase has completed. // canExit reports whether the initial indexing phase has completed.
canExit = func() bool { canExit = func() bool {
return !i.state.is(stateSyncing) && checkDone() return !i.state.is(stateSyncing) && checkDone()
} }
heartBeat = time.NewTicker(15 * time.Second) heartBeat = time.NewTimer(0)
) )
defer heartBeat.Stop()
if recover { if recover {
if aborted := i.recover(); aborted { if aborted := i.recover(); aborted {
return return
@ -507,6 +510,8 @@ func (i *indexIniter) run(recover bool) {
} }
case <-heartBeat.C: case <-heartBeat.C:
heartBeat.Reset(time.Second * 15)
// Short circuit if the indexer is still busy // Short circuit if the indexer is still busy
if done != nil { if done != nil {
continue continue
@ -765,10 +770,10 @@ func checkVersion(disk ethdb.KeyValueStore, typ historyType) {
// newHistoryIndexer constructs the history indexer and launches the background // newHistoryIndexer constructs the history indexer and launches the background
// initer to complete the indexing of any remaining state histories. // initer to complete the indexing of any remaining state histories.
func newHistoryIndexer(disk ethdb.Database, freezer ethdb.AncientStore, lastHistoryID uint64, typ historyType) *historyIndexer { func newHistoryIndexer(disk ethdb.Database, freezer ethdb.AncientStore, lastHistoryID uint64, typ historyType, noWait bool) *historyIndexer {
checkVersion(disk, typ) checkVersion(disk, typ)
return &historyIndexer{ return &historyIndexer{
initer: newIndexIniter(disk, freezer, typ, lastHistoryID), initer: newIndexIniter(disk, freezer, typ, lastHistoryID, noWait),
typ: typ, typ: typ,
disk: disk, disk: disk,
freezer: freezer, freezer: freezer,

View file

@ -67,12 +67,12 @@ type initerState struct {
term chan struct{} term chan struct{}
} }
func newIniterState(disk ethdb.Database) *initerState { func newIniterState(disk ethdb.Database, noWait bool) *initerState {
s := &initerState{ s := &initerState{
disk: disk, disk: disk,
term: make(chan struct{}), term: make(chan struct{}),
} }
go s.update() go s.update(noWait)
return s return s
} }
@ -94,7 +94,7 @@ func (s *initerState) set(state state) {
s.state = state s.state = state
} }
func (s *initerState) update() { func (s *initerState) update(noWait bool) {
ticker := time.NewTicker(time.Minute) ticker := time.NewTicker(time.Minute)
defer ticker.Stop() defer ticker.Stop()
@ -102,6 +102,9 @@ func (s *initerState) update() {
if headBlock != nil && time.Since(time.Unix(int64(headBlock.Time), 0)) < syncStateTimeWindow { if headBlock != nil && time.Since(time.Unix(int64(headBlock.Time), 0)) < syncStateTimeWindow {
s.set(stateSynced) s.set(stateSynced)
log.Info("Marked indexing initer as synced") log.Info("Marked indexing initer as synced")
} else if noWait {
s.set(stateSynced)
log.Info("Marked indexing initer as synced forcibly")
} else { } else {
s.set(stateSyncing) s.set(stateSyncing)
} }

View file

@ -38,7 +38,7 @@ func TestHistoryIndexerShortenDeadlock(t *testing.T) {
rawdb.WriteStateHistory(freezer, uint64(i+1), h.meta.encode(), accountIndex, storageIndex, accountData, storageData) rawdb.WriteStateHistory(freezer, uint64(i+1), h.meta.encode(), accountIndex, storageIndex, accountData, storageData)
} }
// As a workaround, assign a future block to keep the initer running indefinitely // As a workaround, assign a future block to keep the initer running indefinitely
indexer := newHistoryIndexer(db, freezer, 200, typeStateHistory) indexer := newHistoryIndexer(db, freezer, 200, typeStateHistory, true)
defer indexer.close() defer indexer.close()
done := make(chan error, 1) done := make(chan error, 1)