Skip to content

Commit 2380012

Browse files
ARR4Nholiman
andauthored
core/state/snapshot: simplify snapshot rebuild (#30772)
This PR is purely for improved readability; I was doing work involving the file and think this may help others who are trying to understand what's going on. 1. `snapshot.Tree.Rebuild()` now returns a function that blocks until regeneration is complete, allowing `Tree.waitBuild()` to be removed entirely as all it did was search for the `done` channel behind this new function. 2. Its usage inside `New()` is also simplified by (a) only waiting if `!AsyncBuild`; and (b) avoiding the double negative of `if !NoBuild`. --------- Co-authored-by: Martin HS <[email protected]>
1 parent 3c754e2 commit 2380012

File tree

1 file changed

+14
-34
lines changed

1 file changed

+14
-34
lines changed

core/state/snapshot/snapshot.go

Lines changed: 14 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -206,47 +206,24 @@ func New(config Config, diskdb ethdb.KeyValueStore, triedb *triedb.Database, roo
206206
log.Warn("Snapshot maintenance disabled (syncing)")
207207
return snap, nil
208208
}
209-
// Create the building waiter iff the background generation is allowed
210-
if !config.NoBuild && !config.AsyncBuild {
211-
defer snap.waitBuild()
212-
}
213209
if err != nil {
214210
log.Warn("Failed to load snapshot", "err", err)
215-
if !config.NoBuild {
216-
snap.Rebuild(root)
217-
return snap, nil
211+
if config.NoBuild {
212+
return nil, err
213+
}
214+
wait := snap.Rebuild(root)
215+
if !config.AsyncBuild {
216+
wait()
218217
}
219-
return nil, err // Bail out the error, don't rebuild automatically.
218+
return snap, nil
220219
}
221220
// Existing snapshot loaded, seed all the layers
222-
for head != nil {
221+
for ; head != nil; head = head.Parent() {
223222
snap.layers[head.Root()] = head
224-
head = head.Parent()
225223
}
226224
return snap, nil
227225
}
228226

229-
// waitBuild blocks until the snapshot finishes rebuilding. This method is meant
230-
// to be used by tests to ensure we're testing what we believe we are.
231-
func (t *Tree) waitBuild() {
232-
// Find the rebuild termination channel
233-
var done chan struct{}
234-
235-
t.lock.RLock()
236-
for _, layer := range t.layers {
237-
if layer, ok := layer.(*diskLayer); ok {
238-
done = layer.genPending
239-
break
240-
}
241-
}
242-
t.lock.RUnlock()
243-
244-
// Wait until the snapshot is generated
245-
if done != nil {
246-
<-done
247-
}
248-
}
249-
250227
// Disable interrupts any pending snapshot generator, deletes all the snapshot
251228
// layers in memory and marks snapshots disabled globally. In order to resume
252229
// the snapshot functionality, the caller must invoke Rebuild.
@@ -688,8 +665,9 @@ func (t *Tree) Journal(root common.Hash) (common.Hash, error) {
688665

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

@@ -721,9 +699,11 @@ func (t *Tree) Rebuild(root common.Hash) {
721699
// Start generating a new snapshot from scratch on a background thread. The
722700
// generator will run a wiper first if there's not one running right now.
723701
log.Info("Rebuilding state snapshot")
702+
disk := generateSnapshot(t.diskdb, t.triedb, t.config.CacheSize, root)
724703
t.layers = map[common.Hash]snapshot{
725-
root: generateSnapshot(t.diskdb, t.triedb, t.config.CacheSize, root),
704+
root: disk,
726705
}
706+
return func() { <-disk.genPending }
727707
}
728708

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

0 commit comments

Comments
 (0)