core: journal the snapshot inside leveldb, not a flat file
This commit is contained in:
@ -17,12 +17,11 @@
|
||||
package snapshot
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/VictoriaMetrics/fastcache"
|
||||
@ -58,7 +57,7 @@ type journalStorage struct {
|
||||
}
|
||||
|
||||
// loadSnapshot loads a pre-existing state snapshot backed by a key-value store.
|
||||
func loadSnapshot(diskdb ethdb.KeyValueStore, triedb *trie.Database, journal string, cache int, root common.Hash) (snapshot, error) {
|
||||
func loadSnapshot(diskdb ethdb.KeyValueStore, triedb *trie.Database, cache int, root common.Hash) (snapshot, error) {
|
||||
// Retrieve the block number and hash of the snapshot, failing if no snapshot
|
||||
// is present in the database (or crashed mid-update).
|
||||
baseRoot := rawdb.ReadSnapshotRoot(diskdb)
|
||||
@ -71,13 +70,13 @@ func loadSnapshot(diskdb ethdb.KeyValueStore, triedb *trie.Database, journal str
|
||||
cache: fastcache.New(cache * 1024 * 1024),
|
||||
root: baseRoot,
|
||||
}
|
||||
// Open the journal, it must exist since even for 0 layer it stores whether
|
||||
// Retrieve the journal, it must exist since even for 0 layer it stores whether
|
||||
// we've already generated the snapshot or are in progress only
|
||||
file, err := os.Open(journal)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
journal := rawdb.ReadSnapshotJournal(diskdb)
|
||||
if len(journal) == 0 {
|
||||
return nil, errors.New("missing or corrupted snapshot journal")
|
||||
}
|
||||
r := rlp.NewStream(file, 0)
|
||||
r := rlp.NewStream(bytes.NewReader(journal), 0)
|
||||
|
||||
// Read the snapshot generation progress for the disk layer
|
||||
var generator journalGenerator
|
||||
@ -162,9 +161,9 @@ func loadDiffLayer(parent snapshot, r *rlp.Stream) (snapshot, error) {
|
||||
return loadDiffLayer(newDiffLayer(parent, root, accountData, storageData), r)
|
||||
}
|
||||
|
||||
// Journal is the internal version of Journal that also returns the journal file
|
||||
// so subsequent layers know where to write to.
|
||||
func (dl *diskLayer) Journal(path string) (io.WriteCloser, common.Hash, error) {
|
||||
// Journal writes the persistent layer generator stats into a buffer to be stored
|
||||
// in the database as the snapshot journal.
|
||||
func (dl *diskLayer) Journal(buffer *bytes.Buffer) (common.Hash, error) {
|
||||
// If the snapshot is currenty being generated, abort it
|
||||
var stats *generatorStats
|
||||
if dl.genAbort != nil {
|
||||
@ -180,12 +179,7 @@ func (dl *diskLayer) Journal(path string) (io.WriteCloser, common.Hash, error) {
|
||||
defer dl.lock.RUnlock()
|
||||
|
||||
if dl.stale {
|
||||
return nil, common.Hash{}, ErrSnapshotStale
|
||||
}
|
||||
// We've reached the bottom, open the journal
|
||||
file, err := os.Create(path)
|
||||
if err != nil {
|
||||
return nil, common.Hash{}, err
|
||||
return common.Hash{}, ErrSnapshotStale
|
||||
}
|
||||
// Write out the generator marker
|
||||
entry := journalGenerator{
|
||||
@ -198,44 +192,37 @@ func (dl *diskLayer) Journal(path string) (io.WriteCloser, common.Hash, error) {
|
||||
entry.Slots = stats.slots
|
||||
entry.Storage = uint64(stats.storage)
|
||||
}
|
||||
if err := rlp.Encode(file, entry); err != nil {
|
||||
file.Close()
|
||||
return nil, common.Hash{}, err
|
||||
if err := rlp.Encode(buffer, entry); err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
return file, dl.root, nil
|
||||
return dl.root, nil
|
||||
}
|
||||
|
||||
// Journal is the internal version of Journal that also returns the journal file
|
||||
// so subsequent layers know where to write to.
|
||||
func (dl *diffLayer) Journal(path string) (io.WriteCloser, common.Hash, error) {
|
||||
// Journal writes the memory layer contents into a buffer to be stored in the
|
||||
// database as the snapshot journal.
|
||||
func (dl *diffLayer) Journal(buffer *bytes.Buffer) (common.Hash, error) {
|
||||
// Journal the parent first
|
||||
writer, base, err := dl.parent.Journal(path)
|
||||
base, err := dl.parent.Journal(buffer)
|
||||
if err != nil {
|
||||
return nil, common.Hash{}, err
|
||||
return common.Hash{}, err
|
||||
}
|
||||
// Ensure the layer didn't get stale
|
||||
dl.lock.RLock()
|
||||
defer dl.lock.RUnlock()
|
||||
|
||||
if dl.stale {
|
||||
writer.Close()
|
||||
return nil, common.Hash{}, ErrSnapshotStale
|
||||
return common.Hash{}, ErrSnapshotStale
|
||||
}
|
||||
// Everything below was journalled, persist this layer too
|
||||
buf := bufio.NewWriter(writer)
|
||||
if err := rlp.Encode(buf, dl.root); err != nil {
|
||||
buf.Flush()
|
||||
writer.Close()
|
||||
return nil, common.Hash{}, err
|
||||
if err := rlp.Encode(buffer, dl.root); err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
accounts := make([]journalAccount, 0, len(dl.accountData))
|
||||
for hash, blob := range dl.accountData {
|
||||
accounts = append(accounts, journalAccount{Hash: hash, Blob: blob})
|
||||
}
|
||||
if err := rlp.Encode(buf, accounts); err != nil {
|
||||
buf.Flush()
|
||||
writer.Close()
|
||||
return nil, common.Hash{}, err
|
||||
if err := rlp.Encode(buffer, accounts); err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
storage := make([]journalStorage, 0, len(dl.storageData))
|
||||
for hash, slots := range dl.storageData {
|
||||
@ -247,11 +234,8 @@ func (dl *diffLayer) Journal(path string) (io.WriteCloser, common.Hash, error) {
|
||||
}
|
||||
storage = append(storage, journalStorage{Hash: hash, Keys: keys, Vals: vals})
|
||||
}
|
||||
if err := rlp.Encode(buf, storage); err != nil {
|
||||
buf.Flush()
|
||||
writer.Close()
|
||||
return nil, common.Hash{}, err
|
||||
if err := rlp.Encode(buffer, storage); err != nil {
|
||||
return common.Hash{}, err
|
||||
}
|
||||
buf.Flush()
|
||||
return writer, base, nil
|
||||
return base, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user