core/state/snapshot: verify account in range at interruption point

This commit is contained in:
Gary Rong 2024-06-21 16:03:32 +08:00
parent c10ac4f48f
commit 140ee32dbf
3 changed files with 30 additions and 36 deletions

View file

@ -74,6 +74,14 @@ func (dl *diskLayer) Stale() bool {
return dl.stale return dl.stale
} }
// markStale sets the stale flag as true.
func (dl *diskLayer) markStale() {
dl.lock.Lock()
defer dl.lock.Unlock()
dl.stale = true
}
// Account directly retrieves the account associated with a particular hash in // Account directly retrieves the account associated with a particular hash in
// the snapshot slim data format. // the snapshot slim data format.
func (dl *diskLayer) Account(hash common.Hash) (*types.SlimAccount, error) { func (dl *diskLayer) Account(hash common.Hash) (*types.SlimAccount, error) {
@ -175,3 +183,18 @@ func (dl *diskLayer) Storage(accountHash, storageHash common.Hash) ([]byte, erro
func (dl *diskLayer) Update(blockHash common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte) *diffLayer { func (dl *diskLayer) Update(blockHash common.Hash, destructs map[common.Hash]struct{}, accounts map[common.Hash][]byte, storage map[common.Hash]map[common.Hash][]byte) *diffLayer {
return newDiffLayer(dl, blockHash, destructs, accounts, storage) return newDiffLayer(dl, blockHash, destructs, accounts, storage)
} }
// stopGeneration aborts the state snapshot generation if it is currently running.
func (dl *diskLayer) stopGeneration() {
dl.lock.RLock()
generating := dl.genMarker != nil
dl.lock.RUnlock()
if !generating {
return
}
if dl.genAbort != nil {
abort := make(chan *generatorStats)
dl.genAbort <- abort
<-abort
}
}

View file

@ -631,16 +631,10 @@ func generateAccounts(ctx *generatorContext, dl *diskLayer, accMarker []byte) er
accMarker = nil accMarker = nil
return nil return nil
} }
// Always reset the initial account range as 1 whenever recover from the
// interruption. TODO(rjl493456442) can we remove it?
var accountRange = accountCheckRange
if len(accMarker) > 0 {
accountRange = 1
}
origin := common.CopyBytes(accMarker) origin := common.CopyBytes(accMarker)
for { for {
id := trie.StateTrieID(dl.root) id := trie.StateTrieID(dl.root)
exhausted, last, err := dl.generateRange(ctx, id, rawdb.SnapshotAccountPrefix, snapAccount, origin, accountRange, onAccount, types.FullAccountRLP) exhausted, last, err := dl.generateRange(ctx, id, rawdb.SnapshotAccountPrefix, snapAccount, origin, accountCheckRange, onAccount, types.FullAccountRLP)
if err != nil { if err != nil {
return err // The procedure it aborted, either by external signal or internal error. return err // The procedure it aborted, either by external signal or internal error.
} }
@ -652,7 +646,6 @@ func generateAccounts(ctx *generatorContext, dl *diskLayer, accMarker []byte) er
ctx.removeStorageLeft() ctx.removeStorageLeft()
break break
} }
accountRange = accountCheckRange
} }
return nil return nil
} }

View file

@ -258,24 +258,9 @@ func (t *Tree) Disable() {
for _, layer := range t.layers { for _, layer := range t.layers {
switch layer := layer.(type) { switch layer := layer.(type) {
case *diskLayer: case *diskLayer:
layer.stopGeneration()
layer.lock.RLock() layer.markStale()
generating := layer.genMarker != nil layer.Release()
layer.lock.RUnlock()
if !generating {
// Generator is already aborted or finished
break
}
// If the base layer is generating, abort it
if layer.genAbort != nil {
abort := make(chan *generatorStats)
layer.genAbort <- abort
<-abort
}
// Layer should be inactive now, mark it as stale
layer.lock.Lock()
layer.stale = true
layer.lock.Unlock()
case *diffLayer: case *diffLayer:
// If the layer is a simple diff, simply mark as stale // If the layer is a simple diff, simply mark as stale
@ -730,16 +715,9 @@ func (t *Tree) Rebuild(root common.Hash) {
for _, layer := range t.layers { for _, layer := range t.layers {
switch layer := layer.(type) { switch layer := layer.(type) {
case *diskLayer: case *diskLayer:
// If the base layer is generating, abort it and save layer.stopGeneration()
if layer.genAbort != nil { layer.markStale()
abort := make(chan *generatorStats) layer.Release()
layer.genAbort <- abort
<-abort
}
// Layer should be inactive now, mark it as stale
layer.lock.Lock()
layer.stale = true
layer.lock.Unlock()
case *diffLayer: case *diffLayer:
// If the layer is a simple diff, simply mark as stale // If the layer is a simple diff, simply mark as stale