core/state/snapshot: port changes from 29995 (#30040)
#29995 has been reverted due to an unexpected flaw in the state snapshot process. Specifically, it attempts to stop the state snapshot generation, which could potentially cause the system to halt if the generation is not currently running. This pull request ports the changes made in #29995 and fixes the flaw.
This commit is contained in:
parent
88c8459005
commit
d71831255d
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,24 +258,11 @@ 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:
|
||||||
|
// TODO this function will hang if it's called twice. Will
|
||||||
layer.lock.RLock()
|
// fix it in the following PRs.
|
||||||
generating := layer.genMarker != nil
|
layer.stopGeneration()
|
||||||
layer.lock.RUnlock()
|
layer.markStale()
|
||||||
if !generating {
|
layer.Release()
|
||||||
// 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 +717,11 @@ 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
|
// TODO this function will hang if it's called twice. Will
|
||||||
if layer.genAbort != nil {
|
// fix it in the following PRs.
|
||||||
abort := make(chan *generatorStats)
|
layer.stopGeneration()
|
||||||
layer.genAbort <- abort
|
layer.markStale()
|
||||||
<-abort
|
layer.Release()
|
||||||
}
|
|
||||||
// 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
|
||||||
|
|
Loading…
Reference in New Issue