mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-24 21:56:43 +00:00
triedb/pathdb: change to the default datadir
This commit is contained in:
parent
3cc8e23b6a
commit
6bb3dfc8c7
10 changed files with 105 additions and 110 deletions
|
|
@ -446,15 +446,6 @@ var (
|
||||||
Value: ethconfig.Defaults.BlobPool.PriceBump,
|
Value: ethconfig.Defaults.BlobPool.PriceBump,
|
||||||
Category: flags.BlobPoolCategory,
|
Category: flags.BlobPoolCategory,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trie database settings
|
|
||||||
TrieDBJournalFlag = &cli.BoolFlag{
|
|
||||||
Name: "triedb.journal",
|
|
||||||
Usage: "Enable persisting the trie database journal to disk (only used with pbss state scheme, default path: <datadir>/triedb.journal.rlp)",
|
|
||||||
Value: true,
|
|
||||||
Category: flags.TrieDatabaseCategory,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Performance tuning settings
|
// Performance tuning settings
|
||||||
CacheFlag = &cli.IntFlag{
|
CacheFlag = &cli.IntFlag{
|
||||||
Name: "cache",
|
Name: "cache",
|
||||||
|
|
@ -992,7 +983,6 @@ var (
|
||||||
DataDirFlag,
|
DataDirFlag,
|
||||||
AncientFlag,
|
AncientFlag,
|
||||||
EraFlag,
|
EraFlag,
|
||||||
TrieDBJournalFlag,
|
|
||||||
RemoteDBFlag,
|
RemoteDBFlag,
|
||||||
DBEngineFlag,
|
DBEngineFlag,
|
||||||
StateSchemeFlag,
|
StateSchemeFlag,
|
||||||
|
|
@ -1654,9 +1644,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
if ctx.IsSet(StateSchemeFlag.Name) {
|
if ctx.IsSet(StateSchemeFlag.Name) {
|
||||||
cfg.StateScheme = ctx.String(StateSchemeFlag.Name)
|
cfg.StateScheme = ctx.String(StateSchemeFlag.Name)
|
||||||
}
|
}
|
||||||
if !ctx.Bool(TrieDBJournalFlag.Name) {
|
|
||||||
cfg.TrieDBJournal = false
|
|
||||||
}
|
|
||||||
// Parse transaction history flag, if user is still using legacy config
|
// Parse transaction history flag, if user is still using legacy config
|
||||||
// file with 'TxLookupLimit' configured, copy the value to 'TransactionHistory'.
|
// file with 'TxLookupLimit' configured, copy the value to 'TransactionHistory'.
|
||||||
if cfg.TransactionHistory == ethconfig.Defaults.TransactionHistory && cfg.TxLookupLimit != ethconfig.Defaults.TxLookupLimit {
|
if cfg.TransactionHistory == ethconfig.Defaults.TransactionHistory && cfg.TxLookupLimit != ethconfig.Defaults.TxLookupLimit {
|
||||||
|
|
@ -2216,9 +2203,6 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh
|
||||||
options.Preimages = true
|
options.Preimages = true
|
||||||
log.Info("Enabling recording of key preimages since archive mode is used")
|
log.Info("Enabling recording of key preimages since archive mode is used")
|
||||||
}
|
}
|
||||||
if !ctx.Bool(TrieDBJournalFlag.Name) {
|
|
||||||
options.TrieDBJournal = stack.ResolvePath("triedb.journal.rlp")
|
|
||||||
}
|
|
||||||
if !ctx.Bool(SnapshotFlag.Name) {
|
if !ctx.Bool(SnapshotFlag.Name) {
|
||||||
options.SnapshotLimit = 0 // Disabled
|
options.SnapshotLimit = 0 // Disabled
|
||||||
} else if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheSnapshotFlag.Name) {
|
} else if ctx.IsSet(CacheFlag.Name) || ctx.IsSet(CacheSnapshotFlag.Name) {
|
||||||
|
|
|
||||||
|
|
@ -162,11 +162,11 @@ const (
|
||||||
// BlockChainConfig contains the configuration of the BlockChain object.
|
// BlockChainConfig contains the configuration of the BlockChain object.
|
||||||
type BlockChainConfig struct {
|
type BlockChainConfig struct {
|
||||||
// Trie database related options
|
// Trie database related options
|
||||||
TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory
|
TrieCleanLimit int // Memory allowance (MB) to use for caching trie nodes in memory
|
||||||
TrieDirtyLimit int // Memory limit (MB) at which to start flushing dirty trie nodes to disk
|
TrieDirtyLimit int // Memory limit (MB) at which to start flushing dirty trie nodes to disk
|
||||||
TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk
|
TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk
|
||||||
TrieNoAsyncFlush bool // Whether the asynchronous buffer flushing is disallowed
|
TrieNoAsyncFlush bool // Whether the asynchronous buffer flushing is disallowed
|
||||||
TrieDBJournal string // Path to the journal used for persisting trie data across node restarts
|
TrieJournalDirectory string // Directory path to the journal used for persisting trie data across node restarts
|
||||||
|
|
||||||
Preimages bool // Whether to store preimage of trie key to the disk
|
Preimages bool // Whether to store preimage of trie key to the disk
|
||||||
StateHistory uint64 // Number of blocks from head whose state histories are reserved.
|
StateHistory uint64 // Number of blocks from head whose state histories are reserved.
|
||||||
|
|
@ -247,7 +247,7 @@ func (cfg *BlockChainConfig) triedbConfig(isVerkle bool) *triedb.Config {
|
||||||
EnableStateIndexing: cfg.ArchiveMode,
|
EnableStateIndexing: cfg.ArchiveMode,
|
||||||
TrieCleanSize: cfg.TrieCleanLimit * 1024 * 1024,
|
TrieCleanSize: cfg.TrieCleanLimit * 1024 * 1024,
|
||||||
StateCleanSize: cfg.SnapshotLimit * 1024 * 1024,
|
StateCleanSize: cfg.SnapshotLimit * 1024 * 1024,
|
||||||
JournalPath: cfg.TrieDBJournal,
|
JournalDirectory: cfg.TrieJournalDirectory,
|
||||||
|
|
||||||
// TODO(rjl493456442): The write buffer represents the memory limit used
|
// TODO(rjl493456442): The write buffer represents the memory limit used
|
||||||
// for flushing both trie data and state data to disk. The config name
|
// for flushing both trie data and state data to disk. The config name
|
||||||
|
|
|
||||||
|
|
@ -236,14 +236,13 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||||
VmConfig: vm.Config{
|
VmConfig: vm.Config{
|
||||||
EnablePreimageRecording: config.EnablePreimageRecording,
|
EnablePreimageRecording: config.EnablePreimageRecording,
|
||||||
},
|
},
|
||||||
|
// Enables file journaling for the trie database. The journal files will be stored
|
||||||
|
// within the data directory. The corresponding paths will be either:
|
||||||
|
// - DATADIR/merkle.journal
|
||||||
|
// - DATADIR/verkle.journal
|
||||||
|
TrieJournalDirectory: stack.ResolvePath(""),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if config.TrieDBJournal {
|
|
||||||
options.TrieDBJournal = stack.ResolvePath("triedb.journal.rlp")
|
|
||||||
} else {
|
|
||||||
log.Warn("Trie database journal is persisted within the database")
|
|
||||||
}
|
|
||||||
|
|
||||||
if config.VMTrace != "" {
|
if config.VMTrace != "" {
|
||||||
traceConfig := json.RawMessage("{}")
|
traceConfig := json.RawMessage("{}")
|
||||||
if config.VMTraceJsonConfig != "" {
|
if config.VMTraceJsonConfig != "" {
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,12 @@ type Config struct {
|
||||||
LogHistory uint64 `toml:",omitempty"` // The maximum number of blocks from head where a log search index is maintained.
|
LogHistory uint64 `toml:",omitempty"` // The maximum number of blocks from head where a log search index is maintained.
|
||||||
LogNoHistory bool `toml:",omitempty"` // No log search index is maintained.
|
LogNoHistory bool `toml:",omitempty"` // No log search index is maintained.
|
||||||
LogExportCheckpoints string // export log index checkpoints to file
|
LogExportCheckpoints string // export log index checkpoints to file
|
||||||
|
StateHistory uint64 `toml:",omitempty"` // The maximum number of blocks from head whose state histories are reserved.
|
||||||
|
|
||||||
|
// State scheme represents the scheme used to store ethereum states and trie
|
||||||
|
// nodes on top. It can be 'hash', 'path', or none which means use the scheme
|
||||||
|
// consistent with persistent state.
|
||||||
|
StateScheme string `toml:",omitempty"`
|
||||||
|
|
||||||
// RequiredBlocks is a set of block number -> hash mappings which must be in the
|
// RequiredBlocks is a set of block number -> hash mappings which must be in the
|
||||||
// canonical chain of all remote peers. Setting the option makes geth verify the
|
// canonical chain of all remote peers. Setting the option makes geth verify the
|
||||||
|
|
@ -116,20 +122,11 @@ type Config struct {
|
||||||
DatabaseFreezer string
|
DatabaseFreezer string
|
||||||
DatabaseEra string
|
DatabaseEra string
|
||||||
|
|
||||||
// Trie database options. TODO(rjl493456442) move all trie database options
|
|
||||||
// into a separate config structure.
|
|
||||||
TrieCleanCache int
|
TrieCleanCache int
|
||||||
TrieDirtyCache int
|
TrieDirtyCache int
|
||||||
TrieTimeout time.Duration
|
TrieTimeout time.Duration
|
||||||
SnapshotCache int
|
SnapshotCache int
|
||||||
Preimages bool
|
Preimages bool
|
||||||
StateHistory uint64 `toml:",omitempty"` // The maximum number of blocks from head whose state histories are reserved.
|
|
||||||
TrieDBJournal bool // Enable persisting the trie database journal to disk.
|
|
||||||
|
|
||||||
// State scheme represents the scheme used to store ethereum states and trie
|
|
||||||
// nodes on top. It can be 'hash', 'path', or none which means use the scheme
|
|
||||||
// consistent with persistent state.
|
|
||||||
StateScheme string `toml:",omitempty"`
|
|
||||||
|
|
||||||
// This is the number of blocks for which logs will be cached in the filter system.
|
// This is the number of blocks for which logs will be cached in the filter system.
|
||||||
FilterLogCacheSize int
|
FilterLogCacheSize int
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
||||||
LogHistory uint64 `toml:",omitempty"`
|
LogHistory uint64 `toml:",omitempty"`
|
||||||
LogNoHistory bool `toml:",omitempty"`
|
LogNoHistory bool `toml:",omitempty"`
|
||||||
LogExportCheckpoints string
|
LogExportCheckpoints string
|
||||||
|
StateHistory uint64 `toml:",omitempty"`
|
||||||
|
StateScheme string `toml:",omitempty"`
|
||||||
RequiredBlocks map[uint64]common.Hash `toml:"-"`
|
RequiredBlocks map[uint64]common.Hash `toml:"-"`
|
||||||
SkipBcVersionCheck bool `toml:"-"`
|
SkipBcVersionCheck bool `toml:"-"`
|
||||||
DatabaseHandles int `toml:"-"`
|
DatabaseHandles int `toml:"-"`
|
||||||
|
|
@ -41,9 +43,6 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
||||||
TrieTimeout time.Duration
|
TrieTimeout time.Duration
|
||||||
SnapshotCache int
|
SnapshotCache int
|
||||||
Preimages bool
|
Preimages bool
|
||||||
StateHistory uint64 `toml:",omitempty"`
|
|
||||||
TrieDBJournal bool
|
|
||||||
StateScheme string `toml:",omitempty"`
|
|
||||||
FilterLogCacheSize int
|
FilterLogCacheSize int
|
||||||
Miner miner.Config
|
Miner miner.Config
|
||||||
TxPool legacypool.Config
|
TxPool legacypool.Config
|
||||||
|
|
@ -72,6 +71,8 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
||||||
enc.LogHistory = c.LogHistory
|
enc.LogHistory = c.LogHistory
|
||||||
enc.LogNoHistory = c.LogNoHistory
|
enc.LogNoHistory = c.LogNoHistory
|
||||||
enc.LogExportCheckpoints = c.LogExportCheckpoints
|
enc.LogExportCheckpoints = c.LogExportCheckpoints
|
||||||
|
enc.StateHistory = c.StateHistory
|
||||||
|
enc.StateScheme = c.StateScheme
|
||||||
enc.RequiredBlocks = c.RequiredBlocks
|
enc.RequiredBlocks = c.RequiredBlocks
|
||||||
enc.SkipBcVersionCheck = c.SkipBcVersionCheck
|
enc.SkipBcVersionCheck = c.SkipBcVersionCheck
|
||||||
enc.DatabaseHandles = c.DatabaseHandles
|
enc.DatabaseHandles = c.DatabaseHandles
|
||||||
|
|
@ -83,9 +84,6 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
||||||
enc.TrieTimeout = c.TrieTimeout
|
enc.TrieTimeout = c.TrieTimeout
|
||||||
enc.SnapshotCache = c.SnapshotCache
|
enc.SnapshotCache = c.SnapshotCache
|
||||||
enc.Preimages = c.Preimages
|
enc.Preimages = c.Preimages
|
||||||
enc.StateHistory = c.StateHistory
|
|
||||||
enc.TrieDBJournal = c.TrieDBJournal
|
|
||||||
enc.StateScheme = c.StateScheme
|
|
||||||
enc.FilterLogCacheSize = c.FilterLogCacheSize
|
enc.FilterLogCacheSize = c.FilterLogCacheSize
|
||||||
enc.Miner = c.Miner
|
enc.Miner = c.Miner
|
||||||
enc.TxPool = c.TxPool
|
enc.TxPool = c.TxPool
|
||||||
|
|
@ -118,6 +116,8 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
||||||
LogHistory *uint64 `toml:",omitempty"`
|
LogHistory *uint64 `toml:",omitempty"`
|
||||||
LogNoHistory *bool `toml:",omitempty"`
|
LogNoHistory *bool `toml:",omitempty"`
|
||||||
LogExportCheckpoints *string
|
LogExportCheckpoints *string
|
||||||
|
StateHistory *uint64 `toml:",omitempty"`
|
||||||
|
StateScheme *string `toml:",omitempty"`
|
||||||
RequiredBlocks map[uint64]common.Hash `toml:"-"`
|
RequiredBlocks map[uint64]common.Hash `toml:"-"`
|
||||||
SkipBcVersionCheck *bool `toml:"-"`
|
SkipBcVersionCheck *bool `toml:"-"`
|
||||||
DatabaseHandles *int `toml:"-"`
|
DatabaseHandles *int `toml:"-"`
|
||||||
|
|
@ -129,9 +129,6 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
||||||
TrieTimeout *time.Duration
|
TrieTimeout *time.Duration
|
||||||
SnapshotCache *int
|
SnapshotCache *int
|
||||||
Preimages *bool
|
Preimages *bool
|
||||||
StateHistory *uint64 `toml:",omitempty"`
|
|
||||||
TrieDBJournal *bool
|
|
||||||
StateScheme *string `toml:",omitempty"`
|
|
||||||
FilterLogCacheSize *int
|
FilterLogCacheSize *int
|
||||||
Miner *miner.Config
|
Miner *miner.Config
|
||||||
TxPool *legacypool.Config
|
TxPool *legacypool.Config
|
||||||
|
|
@ -189,6 +186,12 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
||||||
if dec.LogExportCheckpoints != nil {
|
if dec.LogExportCheckpoints != nil {
|
||||||
c.LogExportCheckpoints = *dec.LogExportCheckpoints
|
c.LogExportCheckpoints = *dec.LogExportCheckpoints
|
||||||
}
|
}
|
||||||
|
if dec.StateHistory != nil {
|
||||||
|
c.StateHistory = *dec.StateHistory
|
||||||
|
}
|
||||||
|
if dec.StateScheme != nil {
|
||||||
|
c.StateScheme = *dec.StateScheme
|
||||||
|
}
|
||||||
if dec.RequiredBlocks != nil {
|
if dec.RequiredBlocks != nil {
|
||||||
c.RequiredBlocks = dec.RequiredBlocks
|
c.RequiredBlocks = dec.RequiredBlocks
|
||||||
}
|
}
|
||||||
|
|
@ -222,15 +225,6 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
||||||
if dec.Preimages != nil {
|
if dec.Preimages != nil {
|
||||||
c.Preimages = *dec.Preimages
|
c.Preimages = *dec.Preimages
|
||||||
}
|
}
|
||||||
if dec.StateHistory != nil {
|
|
||||||
c.StateHistory = *dec.StateHistory
|
|
||||||
}
|
|
||||||
if dec.TrieDBJournal != nil {
|
|
||||||
c.TrieDBJournal = *dec.TrieDBJournal
|
|
||||||
}
|
|
||||||
if dec.StateScheme != nil {
|
|
||||||
c.StateScheme = *dec.StateScheme
|
|
||||||
}
|
|
||||||
if dec.FilterLogCacheSize != nil {
|
if dec.FilterLogCacheSize != nil {
|
||||||
c.FilterLogCacheSize = *dec.FilterLogCacheSize
|
c.FilterLogCacheSize = *dec.FilterLogCacheSize
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,25 +19,24 @@ package flags
|
||||||
import "github.com/urfave/cli/v2"
|
import "github.com/urfave/cli/v2"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
EthCategory = "ETHEREUM"
|
EthCategory = "ETHEREUM"
|
||||||
BeaconCategory = "BEACON CHAIN"
|
BeaconCategory = "BEACON CHAIN"
|
||||||
DevCategory = "DEVELOPER CHAIN"
|
DevCategory = "DEVELOPER CHAIN"
|
||||||
StateCategory = "STATE HISTORY MANAGEMENT"
|
StateCategory = "STATE HISTORY MANAGEMENT"
|
||||||
TxPoolCategory = "TRANSACTION POOL (EVM)"
|
TxPoolCategory = "TRANSACTION POOL (EVM)"
|
||||||
BlobPoolCategory = "TRANSACTION POOL (BLOB)"
|
BlobPoolCategory = "TRANSACTION POOL (BLOB)"
|
||||||
PerfCategory = "PERFORMANCE TUNING"
|
PerfCategory = "PERFORMANCE TUNING"
|
||||||
AccountCategory = "ACCOUNT"
|
AccountCategory = "ACCOUNT"
|
||||||
APICategory = "API AND CONSOLE"
|
APICategory = "API AND CONSOLE"
|
||||||
NetworkingCategory = "NETWORKING"
|
NetworkingCategory = "NETWORKING"
|
||||||
MinerCategory = "MINER"
|
MinerCategory = "MINER"
|
||||||
TrieDatabaseCategory = "TRIE DATABASE"
|
GasPriceCategory = "GAS PRICE ORACLE"
|
||||||
GasPriceCategory = "GAS PRICE ORACLE"
|
VMCategory = "VIRTUAL MACHINE"
|
||||||
VMCategory = "VIRTUAL MACHINE"
|
LoggingCategory = "LOGGING AND DEBUGGING"
|
||||||
LoggingCategory = "LOGGING AND DEBUGGING"
|
MetricsCategory = "METRICS AND STATS"
|
||||||
MetricsCategory = "METRICS AND STATS"
|
MiscCategory = "MISC"
|
||||||
MiscCategory = "MISC"
|
TestingCategory = "TESTING"
|
||||||
TestingCategory = "TESTING"
|
DeprecatedCategory = "ALIASED (deprecated)"
|
||||||
DeprecatedCategory = "ALIASED (deprecated)"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -120,7 +121,7 @@ type Config struct {
|
||||||
StateCleanSize int // Maximum memory allowance (in bytes) for caching clean state data
|
StateCleanSize int // Maximum memory allowance (in bytes) for caching clean state data
|
||||||
WriteBufferSize int // Maximum memory allowance (in bytes) for write buffer
|
WriteBufferSize int // Maximum memory allowance (in bytes) for write buffer
|
||||||
ReadOnly bool // Flag whether the database is opened in read only mode
|
ReadOnly bool // Flag whether the database is opened in read only mode
|
||||||
JournalPath string // Absolute path of journal file (null means the journal data is persisted in key-value store)
|
JournalDirectory string // Absolute path of journal directory (null means the journal data is persisted in key-value store)
|
||||||
|
|
||||||
// Testing configurations
|
// Testing configurations
|
||||||
SnapshotNoBuild bool // Flag Whether the state generation is allowed
|
SnapshotNoBuild bool // Flag Whether the state generation is allowed
|
||||||
|
|
@ -157,8 +158,8 @@ func (c *Config) fields() []interface{} {
|
||||||
} else {
|
} else {
|
||||||
list = append(list, "history", fmt.Sprintf("last %d blocks", c.StateHistory))
|
list = append(list, "history", fmt.Sprintf("last %d blocks", c.StateHistory))
|
||||||
}
|
}
|
||||||
if c.JournalPath != "" {
|
if c.JournalDirectory != "" {
|
||||||
list = append(list, "journal", c.JournalPath)
|
list = append(list, "journal-dir", c.JournalDirectory)
|
||||||
}
|
}
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
@ -674,6 +675,20 @@ func (db *Database) modifyAllowed() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// journalPath returns the absolute path of journal for persisting state data.
|
||||||
|
func (db *Database) journalPath() string {
|
||||||
|
if db.config.JournalDirectory == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
var fname string
|
||||||
|
if db.isVerkle {
|
||||||
|
fname = fmt.Sprintf("verkle.journal")
|
||||||
|
} else {
|
||||||
|
fname = fmt.Sprintf("merkle.journal")
|
||||||
|
}
|
||||||
|
return filepath.Join(db.config.JournalDirectory, fname)
|
||||||
|
}
|
||||||
|
|
||||||
// AccountHistory inspects the account history within the specified range.
|
// AccountHistory inspects the account history within the specified range.
|
||||||
//
|
//
|
||||||
// Start: State ID of the first history object for the query. 0 implies the first
|
// Start: State ID of the first history object for the query. 0 implies the first
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,7 @@ type tester struct {
|
||||||
snapStorages map[common.Hash]map[common.Hash]map[common.Hash][]byte // Keyed by the hash of account address and the hash of storage key
|
snapStorages map[common.Hash]map[common.Hash]map[common.Hash][]byte // Keyed by the hash of account address and the hash of storage key
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTester(t *testing.T, historyLimit uint64, isVerkle bool, layers int, enableIndex bool, journal string) *tester {
|
func newTester(t *testing.T, historyLimit uint64, isVerkle bool, layers int, enableIndex bool, journalDir string) *tester {
|
||||||
var (
|
var (
|
||||||
disk, _ = rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{Ancient: t.TempDir()})
|
disk, _ = rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{Ancient: t.TempDir()})
|
||||||
db = New(disk, &Config{
|
db = New(disk, &Config{
|
||||||
|
|
@ -135,7 +135,7 @@ func newTester(t *testing.T, historyLimit uint64, isVerkle bool, layers int, ena
|
||||||
StateCleanSize: 256 * 1024,
|
StateCleanSize: 256 * 1024,
|
||||||
WriteBufferSize: 256 * 1024,
|
WriteBufferSize: 256 * 1024,
|
||||||
NoAsyncFlush: true,
|
NoAsyncFlush: true,
|
||||||
JournalPath: journal,
|
JournalDirectory: journalDir,
|
||||||
}, isVerkle)
|
}, isVerkle)
|
||||||
|
|
||||||
obj = &tester{
|
obj = &tester{
|
||||||
|
|
@ -619,14 +619,14 @@ func TestJournal(t *testing.T) {
|
||||||
testJournal(t, filepath.Join(t.TempDir(), strconv.Itoa(rand.Intn(10000))))
|
testJournal(t, filepath.Join(t.TempDir(), strconv.Itoa(rand.Intn(10000))))
|
||||||
}
|
}
|
||||||
|
|
||||||
func testJournal(t *testing.T, journal string) {
|
func testJournal(t *testing.T, journalDir string) {
|
||||||
// Redefine the diff layer depth allowance for faster testing.
|
// Redefine the diff layer depth allowance for faster testing.
|
||||||
maxDiffLayers = 4
|
maxDiffLayers = 4
|
||||||
defer func() {
|
defer func() {
|
||||||
maxDiffLayers = 128
|
maxDiffLayers = 128
|
||||||
}()
|
}()
|
||||||
|
|
||||||
tester := newTester(t, 0, false, 12, false, journal)
|
tester := newTester(t, 0, false, 12, false, journalDir)
|
||||||
defer tester.release()
|
defer tester.release()
|
||||||
|
|
||||||
if err := tester.db.Journal(tester.lastHash()); err != nil {
|
if err := tester.db.Journal(tester.lastHash()); err != nil {
|
||||||
|
|
@ -657,23 +657,23 @@ func TestCorruptedJournal(t *testing.T) {
|
||||||
rawdb.WriteTrieJournal(db, blob)
|
rawdb.WriteTrieJournal(db, blob)
|
||||||
})
|
})
|
||||||
|
|
||||||
path := filepath.Join(t.TempDir(), strconv.Itoa(rand.Intn(10000)))
|
directory := filepath.Join(t.TempDir(), strconv.Itoa(rand.Intn(10000)))
|
||||||
testCorruptedJournal(t, path, func(_ ethdb.Database) {
|
testCorruptedJournal(t, directory, func(_ ethdb.Database) {
|
||||||
f, _ := os.OpenFile(path, os.O_WRONLY, 0644)
|
f, _ := os.OpenFile(filepath.Join(directory, "merkle.journal"), os.O_WRONLY, 0644)
|
||||||
f.WriteAt([]byte{0xa}, 0)
|
f.WriteAt([]byte{0xa}, 0)
|
||||||
f.Sync()
|
f.Sync()
|
||||||
f.Close()
|
f.Close()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func testCorruptedJournal(t *testing.T, journal string, modifyFn func(database ethdb.Database)) {
|
func testCorruptedJournal(t *testing.T, journalDir string, modifyFn func(database ethdb.Database)) {
|
||||||
// Redefine the diff layer depth allowance for faster testing.
|
// Redefine the diff layer depth allowance for faster testing.
|
||||||
maxDiffLayers = 4
|
maxDiffLayers = 4
|
||||||
defer func() {
|
defer func() {
|
||||||
maxDiffLayers = 128
|
maxDiffLayers = 128
|
||||||
}()
|
}()
|
||||||
|
|
||||||
tester := newTester(t, 0, false, 12, false, journal)
|
tester := newTester(t, 0, false, 12, false, journalDir)
|
||||||
defer tester.release()
|
defer tester.release()
|
||||||
|
|
||||||
if err := tester.db.Journal(tester.lastHash()); err != nil {
|
if err := tester.db.Journal(tester.lastHash()); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ func testHistoryReader(t *testing.T, historyLimit uint64) {
|
||||||
}()
|
}()
|
||||||
//log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelDebug, true)))
|
//log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelDebug, true)))
|
||||||
|
|
||||||
env := newTester(t, historyLimit, false, 64, true)
|
env := newTester(t, historyLimit, false, 64, true, "")
|
||||||
defer env.release()
|
defer env.release()
|
||||||
waitIndexing(env.db)
|
waitIndexing(env.db)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
|
@ -33,6 +32,8 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const tempJournalSuffix = ".tmp"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errMissJournal = errors.New("journal not found")
|
errMissJournal = errors.New("journal not found")
|
||||||
errMissVersion = errors.New("version not found")
|
errMissVersion = errors.New("version not found")
|
||||||
|
|
@ -54,12 +55,12 @@ const journalVersion uint64 = 3
|
||||||
// loadJournal tries to parse the layer journal from the disk.
|
// loadJournal tries to parse the layer journal from the disk.
|
||||||
func (db *Database) loadJournal(diskRoot common.Hash) (layer, error) {
|
func (db *Database) loadJournal(diskRoot common.Hash) (layer, error) {
|
||||||
var reader io.Reader
|
var reader io.Reader
|
||||||
if db.config.JournalPath != "" && common.FileExist(db.config.JournalPath) {
|
if path := db.journalPath(); path != "" && common.FileExist(path) {
|
||||||
// If a journal file is specified, read it from there
|
// If a journal file is specified, read it from there
|
||||||
log.Info("Load database journal from file", "path", db.config.JournalPath)
|
log.Info("Load database journal from file", "path", path)
|
||||||
f, err := os.OpenFile(db.config.JournalPath, os.O_RDONLY, 0644)
|
f, err := os.OpenFile(path, os.O_RDONLY, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to read journal file %s: %w", db.config.JournalPath, err)
|
return nil, fmt.Errorf("failed to read journal file %s: %w", path, err)
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
reader = f
|
reader = f
|
||||||
|
|
@ -335,22 +336,26 @@ func (db *Database) Journal(root common.Hash) error {
|
||||||
|
|
||||||
// Store the journal into the database and return
|
// Store the journal into the database and return
|
||||||
var (
|
var (
|
||||||
file *os.File
|
file *os.File
|
||||||
journal io.Writer
|
journal io.Writer
|
||||||
tmpName = db.config.JournalPath + ".tmp"
|
journalPath = db.journalPath()
|
||||||
)
|
)
|
||||||
if db.config.JournalPath != "" {
|
if journalPath != "" {
|
||||||
// Write into a temp file first
|
// Write into a temp file first
|
||||||
var err error
|
err := os.Mkdir(db.config.JournalDirectory, 0755)
|
||||||
file, err = os.OpenFile(tmpName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to open journal file %s: %w", tmpName, err)
|
return err
|
||||||
|
}
|
||||||
|
tmp := journalPath + tempJournalSuffix
|
||||||
|
file, err = os.OpenFile(tmp, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to open journal file %s: %w", tmp, err)
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if file != nil {
|
if file != nil {
|
||||||
file.Close()
|
file.Close()
|
||||||
os.Remove(tmpName) // Clean up temp file if we didn't successfully rename it
|
os.Remove(tmp) // Clean up temp file if we didn't successfully rename it
|
||||||
log.Warn("Removed leftover temporary journal file", "path", tmpName)
|
log.Warn("Removed leftover temporary journal file", "path", tmp)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
journal = file
|
journal = file
|
||||||
|
|
@ -377,14 +382,17 @@ func (db *Database) Journal(root common.Hash) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the journal into the database and return
|
// Store the journal into the database and return
|
||||||
var size int
|
if file == nil {
|
||||||
if db.config.JournalPath == "" {
|
|
||||||
data := journal.(*bytes.Buffer)
|
data := journal.(*bytes.Buffer)
|
||||||
size = data.Len()
|
size := data.Len()
|
||||||
rawdb.WriteTrieJournal(db.diskdb, data.Bytes())
|
rawdb.WriteTrieJournal(db.diskdb, data.Bytes())
|
||||||
|
log.Info("Persisted dirty state to disk", "size", common.StorageSize(size), "elapsed", common.PrettyDuration(time.Since(start)))
|
||||||
} else {
|
} else {
|
||||||
stat, _ := journal.(*os.File).Stat()
|
stat, err := file.Stat()
|
||||||
size = int(stat.Size())
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
size := int(stat.Size())
|
||||||
|
|
||||||
// Close the temporary file and atomically rename it
|
// Close the temporary file and atomically rename it
|
||||||
if err := file.Sync(); err != nil {
|
if err := file.Sync(); err != nil {
|
||||||
|
|
@ -394,17 +402,16 @@ func (db *Database) Journal(root common.Hash) error {
|
||||||
return fmt.Errorf("failed to close the journal: %v", err)
|
return fmt.Errorf("failed to close the journal: %v", err)
|
||||||
}
|
}
|
||||||
// Replace the live journal with the newly generated one
|
// Replace the live journal with the newly generated one
|
||||||
if err := os.Rename(tmpName, db.config.JournalPath); err != nil {
|
if err := os.Rename(journalPath+tempJournalSuffix, journalPath); err != nil {
|
||||||
return fmt.Errorf("failed to rename the journal: %v", err)
|
return fmt.Errorf("failed to rename the journal: %v", err)
|
||||||
}
|
}
|
||||||
if err := syncDir(filepath.Dir(db.config.JournalPath)); err != nil {
|
if err := syncDir(db.config.JournalDirectory); err != nil {
|
||||||
return fmt.Errorf("failed to fsync the dir: %v", err)
|
return fmt.Errorf("failed to fsync the dir: %v", err)
|
||||||
}
|
}
|
||||||
file = nil
|
file = nil
|
||||||
|
log.Info("Persisted dirty state to file", "path", journalPath, "size", common.StorageSize(size), "elapsed", common.PrettyDuration(time.Since(start)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the db in read only mode to reject all following mutations
|
// Set the db in read only mode to reject all following mutations
|
||||||
db.readOnly = true
|
db.readOnly = true
|
||||||
log.Info("Persisted dirty state to disk", "size", common.StorageSize(size), "elapsed", common.PrettyDuration(time.Since(start)))
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue