Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core/state/snapshot: simplify snapshot rebuild #30772

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 14 additions & 34 deletions core/state/snapshot/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,47 +206,24 @@ func New(config Config, diskdb ethdb.KeyValueStore, triedb *triedb.Database, roo
log.Warn("Snapshot maintenance disabled (syncing)")
return snap, nil
}
// Create the building waiter iff the background generation is allowed
if !config.NoBuild && !config.AsyncBuild {
defer snap.waitBuild()
}
if err != nil {
log.Warn("Failed to load snapshot", "err", err)
if !config.NoBuild {
snap.Rebuild(root)
return snap, nil
if config.NoBuild {
return nil, err
}
wait := snap.Rebuild(root)
if !config.AsyncBuild {
wait()
}
return nil, err // Bail out the error, don't rebuild automatically.
return snap, nil
}
// Existing snapshot loaded, seed all the layers
for head != nil {
for ; head != nil; head = head.Parent() {
snap.layers[head.Root()] = head
head = head.Parent()
}
return snap, nil
}

// waitBuild blocks until the snapshot finishes rebuilding. This method is meant
// to be used by tests to ensure we're testing what we believe we are.
func (t *Tree) waitBuild() {
// Find the rebuild termination channel
var done chan struct{}

t.lock.RLock()
for _, layer := range t.layers {
if layer, ok := layer.(*diskLayer); ok {
done = layer.genPending
break
}
}
t.lock.RUnlock()

// Wait until the snapshot is generated
if done != nil {
<-done
}
}

// Disable interrupts any pending snapshot generator, deletes all the snapshot
// layers in memory and marks snapshots disabled globally. In order to resume
// the snapshot functionality, the caller must invoke Rebuild.
Expand Down Expand Up @@ -703,8 +680,9 @@ func (t *Tree) Journal(root common.Hash) (common.Hash, error) {

// Rebuild wipes all available snapshot data from the persistent database and
// discard all caches and diff layers. Afterwards, it starts a new snapshot
// generator with the given root hash.
func (t *Tree) Rebuild(root common.Hash) {
// generator with the given root hash. The returned function blocks until
// regeneration is complete.
func (t *Tree) Rebuild(root common.Hash) (wait func()) {
t.lock.Lock()
defer t.lock.Unlock()

Expand Down Expand Up @@ -736,9 +714,11 @@ func (t *Tree) Rebuild(root common.Hash) {
// Start generating a new snapshot from scratch on a background thread. The
// generator will run a wiper first if there's not one running right now.
log.Info("Rebuilding state snapshot")
disk := generateSnapshot(t.diskdb, t.triedb, t.config.CacheSize, root)
t.layers = map[common.Hash]snapshot{
root: generateSnapshot(t.diskdb, t.triedb, t.config.CacheSize, root),
root: disk,
}
return func() { <-disk.genPending }
}

// AccountIterator creates a new account iterator for the specified root hash and
Expand Down