mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-02 18:13:44 +00:00
Merge pull request #32 from DeBankDeFi/discard-ancient
implemented online ancient db pruning
This commit is contained in:
commit
7cdb63ee31
10 changed files with 71 additions and 133 deletions
|
|
@ -192,7 +192,7 @@ func initGenesis(ctx *cli.Context) error {
|
|||
stack, _ := makeConfigNode(ctx)
|
||||
defer stack.Close()
|
||||
for _, name := range []string{"chaindata", "lightchaindata"} {
|
||||
chaindb, err := stack.OpenDatabaseWithFreezer(name, 0, 0, ctx.GlobalString(utils.AncientFlag.Name), "", false, ctx.GlobalUint64(utils.AncientRecentLimitFlag.Name))
|
||||
chaindb, err := stack.OpenDatabaseWithFreezer(name, 0, 0, ctx.GlobalString(utils.AncientFlag.Name), "", false, ctx.GlobalBool(utils.AncientPruneFlag.Name))
|
||||
if err != nil {
|
||||
utils.Fatalf("Failed to open database: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,10 +123,9 @@ var (
|
|||
Name: "datadir.ancient",
|
||||
Usage: "Data directory for ancient chain segments (default = inside chaindata)",
|
||||
}
|
||||
AncientRecentLimitFlag = cli.Uint64Flag{
|
||||
Name: "ancient.recentlimit",
|
||||
Usage: "Keep only the specified amount of recent ancient blocks and won't do ancient related checks on startup (default = 0, means keep all)",
|
||||
Value: 0,
|
||||
AncientPruneFlag = cli.BoolFlag{
|
||||
Name: "ancient.prune",
|
||||
Usage: "Totally discard the ancient blocks instead of writing them to the freezer db",
|
||||
}
|
||||
MinFreeDiskSpaceFlag = DirectoryFlag{
|
||||
Name: "datadir.minfreedisk",
|
||||
|
|
@ -865,7 +864,7 @@ var (
|
|||
DatabasePathFlags = []cli.Flag{
|
||||
DataDirFlag,
|
||||
AncientFlag,
|
||||
AncientRecentLimitFlag,
|
||||
AncientPruneFlag,
|
||||
RemoteDBFlag,
|
||||
}
|
||||
)
|
||||
|
|
@ -1615,8 +1614,8 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
|||
ctx.GlobalSet(TxLookupLimitFlag.Name, "0")
|
||||
log.Warn("Disable transaction unindexing for archive node")
|
||||
}
|
||||
if ctx.GlobalString(GCModeFlag.Name) == "archive" && ctx.GlobalUint64(AncientRecentLimitFlag.Name) != 0 {
|
||||
ctx.GlobalSet(AncientRecentLimitFlag.Name, "0")
|
||||
if ctx.GlobalString(GCModeFlag.Name) == "archive" && ctx.GlobalUint64(AncientPruneFlag.Name) != 0 {
|
||||
ctx.GlobalSet(AncientPruneFlag.Name, "false")
|
||||
log.Warn("Disable ancient prunning for archive node")
|
||||
}
|
||||
if ctx.GlobalIsSet(LightServeFlag.Name) && ctx.GlobalUint64(TxLookupLimitFlag.Name) != 0 {
|
||||
|
|
@ -1686,8 +1685,8 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
|||
if ctx.GlobalIsSet(TxLookupLimitFlag.Name) {
|
||||
cfg.TxLookupLimit = ctx.GlobalUint64(TxLookupLimitFlag.Name)
|
||||
}
|
||||
if ctx.GlobalIsSet(AncientRecentLimitFlag.Name) {
|
||||
cfg.AncientRecentLimit = ctx.GlobalUint64(AncientRecentLimitFlag.Name)
|
||||
if ctx.GlobalIsSet(AncientPruneFlag.Name) {
|
||||
cfg.AncientPrune = ctx.GlobalBool(AncientPruneFlag.Name)
|
||||
}
|
||||
if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheTrieFlag.Name) {
|
||||
cfg.TrieCleanCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheTrieFlag.Name) / 100
|
||||
|
|
@ -2012,7 +2011,7 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb.
|
|||
case ctx.GlobalString(SyncModeFlag.Name) == "light":
|
||||
chainDb, err = stack.OpenDatabase("lightchaindata", cache, handles, "", readonly)
|
||||
default:
|
||||
chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.GlobalString(AncientFlag.Name), "", readonly, ctx.GlobalUint64(AncientRecentLimitFlag.Name))
|
||||
chainDb, err = stack.OpenDatabaseWithFreezer("chaindata", cache, handles, ctx.GlobalString(AncientFlag.Name), "", readonly, ctx.GlobalBool(AncientPruneFlag.Name))
|
||||
}
|
||||
if err != nil {
|
||||
Fatalf("Could not open database: %v", err)
|
||||
|
|
|
|||
|
|
@ -143,8 +143,7 @@ type CacheConfig struct {
|
|||
SnapshotLimit int // Memory allowance (MB) to use for caching snapshot entries in memory
|
||||
Preimages bool // Whether to store preimage of trie key to the disk
|
||||
|
||||
AncientRecentLimit uint64
|
||||
|
||||
AncientPrune bool
|
||||
SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it
|
||||
}
|
||||
|
||||
|
|
@ -425,6 +424,9 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
|
|||
// Start tx indexer/unindexer.
|
||||
if txLookupLimit != nil {
|
||||
bc.txLookupLimit = *txLookupLimit
|
||||
if bc.cacheConfig.AncientPrune {
|
||||
bc.txLookupLimit = params.FullImmutabilityThreshold
|
||||
}
|
||||
|
||||
bc.wg.Add(1)
|
||||
go bc.maintainTxIndex(txIndexBlock)
|
||||
|
|
@ -960,6 +962,10 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
|||
bc.wg.Add(1)
|
||||
defer bc.wg.Done()
|
||||
|
||||
if bc.cacheConfig.AncientPrune {
|
||||
ancientLimit = 0
|
||||
}
|
||||
|
||||
var (
|
||||
ancientBlocks, liveBlocks types.Blocks
|
||||
ancientReceipts, liveReceipts []types.Receipts
|
||||
|
|
@ -2293,38 +2299,19 @@ func (bc *BlockChain) skipBlock(err error, it *insertIterator) bool {
|
|||
func (bc *BlockChain) maintainTxIndex(ancients uint64) {
|
||||
defer bc.wg.Done()
|
||||
|
||||
ancientLimit := bc.cacheConfig.AncientRecentLimit
|
||||
frozen, _ := bc.db.Ancients()
|
||||
log.Info("maintainTxIndex", "ancientLimit", ancientLimit, "ancients", ancients, "frozen", frozen)
|
||||
// Before starting the actual maintenance, we need to handle a special case,
|
||||
// where user might init Geth with an external ancient database. If so, we
|
||||
// need to reindex all necessary transactions before starting to process any
|
||||
// pruning requests.
|
||||
if ancients > 0 {
|
||||
var from = uint64(0)
|
||||
// let `from` be a "more" recent block
|
||||
if ancientLimit > 0 {
|
||||
if ancientLimit < ancients {
|
||||
from = ancients - ancientLimit
|
||||
}
|
||||
if bc.txLookupLimit != 0 && bc.txLookupLimit < ancientLimit {
|
||||
from = ancients - bc.txLookupLimit
|
||||
}
|
||||
} else {
|
||||
if bc.txLookupLimit != 0 && ancients > bc.txLookupLimit {
|
||||
from = ancients - bc.txLookupLimit
|
||||
}
|
||||
if bc.txLookupLimit != 0 && ancients > bc.txLookupLimit {
|
||||
from = ancients - bc.txLookupLimit
|
||||
}
|
||||
|
||||
log.Info("maintainTxIndex", "ancientLimit", ancientLimit, "ancients", ancients, "from", from)
|
||||
rawdb.IndexTransactions(bc.db, from, ancients, bc.quit)
|
||||
}
|
||||
|
||||
if ancientLimit > 0 && (bc.txLookupLimit == 0 || bc.txLookupLimit > ancientLimit) {
|
||||
log.Warn("reduece txLookupLimit to meet ancient purging purpose, as it's insane to lookup txs in purged blocks")
|
||||
bc.txLookupLimit = ancientLimit
|
||||
}
|
||||
|
||||
// indexBlocks reindexes or unindexes transactions depending on user configuration
|
||||
indexBlocks := func(tail *uint64, head uint64, done chan struct{}) {
|
||||
defer func() { done <- struct{}{} }()
|
||||
|
|
@ -2337,8 +2324,8 @@ func (bc *BlockChain) maintainTxIndex(ancients uint64) {
|
|||
rawdb.WriteTxIndexTail(bc.db, 0)
|
||||
} else {
|
||||
// Prune all stale tx indices and record the tx index tail
|
||||
log.Info("Scheduled transactions unindexing", "from block", 0, "to", head-bc.txLookupLimit+1)
|
||||
rawdb.UnindexTransactions(bc.db, 0, head-bc.txLookupLimit+1, bc.quit)
|
||||
log.Info("Scheduled blocks & transactions unindexing", "from block", 0, "to", head-bc.txLookupLimit+1)
|
||||
rawdb.UnindexTransactions(bc.db, 0, head-bc.txLookupLimit+1, bc.quit, bc.cacheConfig.AncientPrune)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -2362,61 +2349,14 @@ func (bc *BlockChain) maintainTxIndex(ancients uint64) {
|
|||
rawdb.IndexTransactions(bc.db, head-bc.txLookupLimit+1, *tail, bc.quit)
|
||||
} else {
|
||||
// Unindex a part of stale indices and forward index tail to HEAD-limit
|
||||
log.Info("Scheduled transactions unindexing", "from block", *tail, "to", head-bc.txLookupLimit+1)
|
||||
rawdb.UnindexTransactions(bc.db, *tail, head-bc.txLookupLimit+1, bc.quit)
|
||||
log.Info("Scheduled blocks & transactions unindexing", "from block", *tail, "to", head-bc.txLookupLimit+1)
|
||||
rawdb.UnindexTransactions(bc.db, *tail, head-bc.txLookupLimit+1, bc.quit, bc.cacheConfig.AncientPrune)
|
||||
}
|
||||
}
|
||||
|
||||
// pruneAncient is a background thread that periodically checks the blockchain for any
|
||||
// import progress and cleans ancient data from the freezer.
|
||||
//
|
||||
// it calculates the highest block(named `cleanTo`) that can be cleaned, then starts
|
||||
// cleaning from the genesis+1 block in batches, until reaches the `cleanTo` block.
|
||||
pruneAncient := func(txIndexTail *uint64, head uint64, wait, done chan struct{}) {
|
||||
defer func() { done <- struct{}{} }()
|
||||
// Wait till the tx index routine finishes, in case that it cannot find the ancient
|
||||
// blocks for iterating transactions for unindex because we have pruned the blocks
|
||||
<-wait
|
||||
|
||||
start := time.Now()
|
||||
|
||||
first, _ := bc.db.Tail()
|
||||
last, _ := bc.db.Ancients()
|
||||
ancientLimit := bc.cacheConfig.AncientRecentLimit
|
||||
|
||||
if last < ancientLimit || last < first {
|
||||
// It should not reach here
|
||||
log.Error("prune ancient error", "last frozen", last, "first frozen", first, "ancientRecentLimit", ancientLimit)
|
||||
return
|
||||
}
|
||||
|
||||
pruneTo := last - ancientLimit
|
||||
storedSections := rawdb.ReadStoredBloomSections(bc.db)
|
||||
if storedSections*params.BloomBitsBlocks-1 < pruneTo {
|
||||
log.Warn("Attempt to prune the ancient blocks that bloom filter haven't finished yet, postpone to next round", "storedSections", storedSections, "pruneTo", pruneTo)
|
||||
return
|
||||
}
|
||||
|
||||
// Double ensure we don't prune the blocks having dangling transaction indices
|
||||
if txIndexTail != nil && pruneTo > *txIndexTail {
|
||||
log.Warn("Attempt to prune the ancient blocks that still have tx indices, postpone to next round", "txIndexTail", *txIndexTail, "pruneTo", pruneTo)
|
||||
return
|
||||
}
|
||||
|
||||
// truncate
|
||||
bc.db.TruncateTail(pruneTo)
|
||||
|
||||
// Log something friendly for the user
|
||||
context := []interface{}{
|
||||
"blocks", pruneTo - first, "from block", first, "to", pruneTo, "current last block in ancient", last, "elapsed", common.PrettyDuration(time.Since(start)),
|
||||
}
|
||||
log.Info("Cleaned ancient chain segment", context...)
|
||||
}
|
||||
|
||||
// Any reindexing done, start listening to chain events and moving the index window
|
||||
var (
|
||||
doneTx chan struct{} // For tx indexing routine, non-nil if the routine is active.
|
||||
donePr chan struct{} // For prune ancient routine, non-nil if the routine is active.
|
||||
done chan struct{} // For tx indexing routine, non-nil if the routine is active.
|
||||
headCh = make(chan ChainHeadEvent, 1) // Buffered to avoid locking up the event feed
|
||||
)
|
||||
sub := bc.SubscribeChainHeadEvent(headCh)
|
||||
|
|
@ -2428,19 +2368,16 @@ func (bc *BlockChain) maintainTxIndex(ancients uint64) {
|
|||
for {
|
||||
select {
|
||||
case head := <-headCh:
|
||||
if doneTx == nil && donePr == nil {
|
||||
doneTx = make(chan struct{})
|
||||
donePr = make(chan struct{})
|
||||
go indexBlocks(rawdb.ReadTxIndexTail(bc.db), head.Block.NumberU64(), doneTx)
|
||||
go pruneAncient(rawdb.ReadTxIndexTail(bc.db), head.Block.NumberU64(), doneTx, donePr)
|
||||
if done == nil {
|
||||
done = make(chan struct{})
|
||||
go indexBlocks(rawdb.ReadTxIndexTail(bc.db), head.Block.NumberU64(), done)
|
||||
}
|
||||
case <-donePr:
|
||||
donePr = nil
|
||||
doneTx = nil
|
||||
case <-done:
|
||||
done = nil
|
||||
case <-bc.quit:
|
||||
if donePr != nil {
|
||||
if done != nil {
|
||||
log.Info("Waiting background transaction indexer and ancient pruner to exit")
|
||||
<-donePr
|
||||
<-done
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,10 +37,6 @@ const (
|
|||
// freezerBatchLimit is the maximum number of blocks to freeze in one batch
|
||||
// before doing an fsync and deleting it from the key-value store.
|
||||
freezerBatchLimit = 30000
|
||||
|
||||
// cleanerRecheckInterval is the frequency to check the freezer database to
|
||||
// find the bloks that might be pruned
|
||||
cleanerRecheckInterval = 1 * time.Minute
|
||||
)
|
||||
|
||||
// chainFreezer is a wrapper of freezer with additional chain freezing feature.
|
||||
|
|
@ -52,10 +48,6 @@ type chainFreezer struct {
|
|||
// so take advantage of that (https://golang.org/pkg/sync/atomic/#pkg-note-BUG).
|
||||
threshold uint64 // Number of recent blocks not to freeze (params.FullImmutabilityThreshold apart from tests)
|
||||
|
||||
// ancientRecentLimit Number of recent blocks to keep in ancient db
|
||||
// if not 0, blocks older than `HEAD - ancientRecentLimit` will be purged from ancient db
|
||||
ancientRecentLimit uint64
|
||||
|
||||
*Freezer
|
||||
quit chan struct{}
|
||||
wg sync.WaitGroup
|
||||
|
|
@ -63,17 +55,16 @@ type chainFreezer struct {
|
|||
}
|
||||
|
||||
// newChainFreezer initializes the freezer for ancient chain data.
|
||||
func newChainFreezer(datadir string, namespace string, readonly bool, maxTableSize uint32, tables map[string]bool, ancientRecentLimit uint64) (*chainFreezer, error) {
|
||||
func newChainFreezer(datadir string, namespace string, readonly bool, maxTableSize uint32, tables map[string]bool) (*chainFreezer, error) {
|
||||
freezer, err := NewFreezer(datadir, namespace, readonly, maxTableSize, tables)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &chainFreezer{
|
||||
Freezer: freezer,
|
||||
ancientRecentLimit: ancientRecentLimit,
|
||||
threshold: params.FullImmutabilityThreshold,
|
||||
quit: make(chan struct{}),
|
||||
trigger: make(chan chan struct{}),
|
||||
Freezer: freezer,
|
||||
threshold: params.FullImmutabilityThreshold,
|
||||
quit: make(chan struct{}),
|
||||
trigger: make(chan chan struct{}),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -84,8 +84,9 @@ func InitDatabaseFromFreezer(db ethdb.Database) {
|
|||
}
|
||||
|
||||
type blockTxHashes struct {
|
||||
number uint64
|
||||
hashes []common.Hash
|
||||
number uint64
|
||||
blockHash common.Hash
|
||||
hashes []common.Hash
|
||||
}
|
||||
|
||||
// iterateTransactions iterates over all transactions in the (canon) block
|
||||
|
|
@ -96,6 +97,7 @@ func iterateTransactions(db ethdb.Database, from uint64, to uint64, reverse bool
|
|||
// One thread sequentially reads data from db
|
||||
type numberRlp struct {
|
||||
number uint64
|
||||
hash common.Hash
|
||||
rlp rlp.RawValue
|
||||
}
|
||||
if to == from {
|
||||
|
|
@ -118,9 +120,10 @@ func iterateTransactions(db ethdb.Database, from uint64, to uint64, reverse bool
|
|||
defer close(rlpCh)
|
||||
for n != end {
|
||||
data := ReadCanonicalBodyRLP(db, n)
|
||||
hash := ReadCanonicalHash(db, n)
|
||||
// Feed the block to the aggregator, or abort on interrupt
|
||||
select {
|
||||
case rlpCh <- &numberRlp{n, data}:
|
||||
case rlpCh <- &numberRlp{n, hash, data}:
|
||||
case <-interrupt:
|
||||
return
|
||||
}
|
||||
|
|
@ -151,8 +154,9 @@ func iterateTransactions(db ethdb.Database, from uint64, to uint64, reverse bool
|
|||
hashes = append(hashes, tx.Hash())
|
||||
}
|
||||
result := &blockTxHashes{
|
||||
hashes: hashes,
|
||||
number: data.number,
|
||||
hashes: hashes,
|
||||
blockHash: data.hash,
|
||||
number: data.number,
|
||||
}
|
||||
// Feed the block to the aggregator, or abort on interrupt
|
||||
select {
|
||||
|
|
@ -269,7 +273,7 @@ func indexTransactionsForTesting(db ethdb.Database, from uint64, to uint64, inte
|
|||
//
|
||||
// There is a passed channel, the whole procedure will be interrupted if any
|
||||
// signal received.
|
||||
func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool) {
|
||||
func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool, unindexBlock bool) {
|
||||
// short circuit for invalid range
|
||||
if from >= to {
|
||||
return
|
||||
|
|
@ -303,6 +307,10 @@ func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt ch
|
|||
nextNum = delivery.number + 1
|
||||
DeleteTxLookupEntries(batch, delivery.hashes)
|
||||
txs += len(delivery.hashes)
|
||||
// Delete all about the block
|
||||
if unindexBlock && delivery.number != 0 { // never delete the genesis block
|
||||
DeleteBlock(batch, delivery.blockHash, delivery.number)
|
||||
}
|
||||
blocks++
|
||||
|
||||
// If enough data was accumulated in memory or we're at the last block, dump to disk
|
||||
|
|
@ -344,11 +352,11 @@ func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt ch
|
|||
//
|
||||
// There is a passed channel, the whole procedure will be interrupted if any
|
||||
// signal received.
|
||||
func UnindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}) {
|
||||
unindexTransactions(db, from, to, interrupt, nil)
|
||||
func UnindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, unindexBlock bool) {
|
||||
unindexTransactions(db, from, to, interrupt, nil, unindexBlock)
|
||||
}
|
||||
|
||||
// unindexTransactionsForTesting is the internal debug version with an additional hook.
|
||||
func unindexTransactionsForTesting(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool) {
|
||||
unindexTransactions(db, from, to, interrupt, hook)
|
||||
unindexTransactions(db, from, to, interrupt, hook, false)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -169,11 +169,11 @@ func TestIndexTransactions(t *testing.T) {
|
|||
IndexTransactions(chainDb, 0, 5, nil)
|
||||
verify(0, 11, true, 0)
|
||||
|
||||
UnindexTransactions(chainDb, 0, 5, nil)
|
||||
UnindexTransactions(chainDb, 0, 5, nil, false)
|
||||
verify(5, 11, true, 5)
|
||||
verify(0, 5, false, 5)
|
||||
|
||||
UnindexTransactions(chainDb, 5, 11, nil)
|
||||
UnindexTransactions(chainDb, 5, 11, nil, false)
|
||||
verify(0, 11, false, 11)
|
||||
|
||||
// Testing corner cases
|
||||
|
|
|
|||
|
|
@ -165,9 +165,9 @@ func NewDatabase(db ethdb.KeyValueStore) ethdb.Database {
|
|||
// NewDatabaseWithFreezer creates a high level database on top of a given key-
|
||||
// value data store with a freezer moving immutable chain segments into cold
|
||||
// storage.
|
||||
func NewDatabaseWithFreezer(db ethdb.KeyValueStore, freezer string, namespace string, readonly bool, ancientRecentLimit uint64) (ethdb.Database, error) {
|
||||
func NewDatabaseWithFreezer(db ethdb.KeyValueStore, freezer string, namespace string, readonly, ancientPrune bool) (ethdb.Database, error) {
|
||||
// Create the idle freezer instance
|
||||
frdb, err := newChainFreezer(freezer, namespace, readonly, freezerTableSize, FreezerNoSnappy, ancientRecentLimit)
|
||||
frdb, err := newChainFreezer(freezer, namespace, readonly, freezerTableSize, FreezerNoSnappy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -194,7 +194,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, freezer string, namespace st
|
|||
// validate in this method. If, however, the genesis hash is not nil, compare
|
||||
// it to the freezer content.
|
||||
// TODO consider deprecate this check
|
||||
if kvgenesis, _ := db.Get(headerHashKey(0)); len(kvgenesis) > 0 && frdb.ancientRecentLimit == 0 {
|
||||
if kvgenesis, _ := db.Get(headerHashKey(0)); len(kvgenesis) > 0 && !ancientPrune {
|
||||
if frozen, _ := frdb.Ancients(); frozen > 0 {
|
||||
// If the freezer already contains something, ensure that the genesis blocks
|
||||
// match, otherwise we might mix up freezers across chains and destroy both
|
||||
|
|
@ -237,7 +237,7 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, freezer string, namespace st
|
|||
}
|
||||
}
|
||||
// Freezer is consistent with the key-value database, permit combining the two
|
||||
if !frdb.readonly {
|
||||
if !frdb.readonly && !ancientPrune {
|
||||
frdb.wg.Add(1)
|
||||
go func() {
|
||||
frdb.freeze(db)
|
||||
|
|
@ -275,12 +275,13 @@ func NewLevelDBDatabase(file string, cache int, handles int, namespace string, r
|
|||
|
||||
// NewLevelDBDatabaseWithFreezer creates a persistent key-value database with a
|
||||
// freezer moving immutable chain segments into cold storage.
|
||||
func NewLevelDBDatabaseWithFreezer(file string, cache int, handles int, freezer string, namespace string, readonly bool, ancientRecentLimit uint64) (ethdb.Database, error) {
|
||||
func NewLevelDBDatabaseWithFreezer(file string, cache int, handles int, freezer string, namespace string, readonly, ancientPrune bool) (ethdb.Database, error) {
|
||||
kvdb, err := leveldb.New(file, cache, handles, namespace, readonly)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
frdb, err := NewDatabaseWithFreezer(kvdb, freezer, namespace, readonly, ancientRecentLimit)
|
||||
|
||||
frdb, err := NewDatabaseWithFreezer(kvdb, freezer, namespace, readonly, ancientPrune)
|
||||
if err != nil {
|
||||
kvdb.Close()
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
|||
ethashConfig.NotifyFull = config.Miner.NotifyFull
|
||||
|
||||
// Assemble the Ethereum object
|
||||
chainDb, err := stack.OpenDatabaseWithFreezer("chaindata", config.DatabaseCache, config.DatabaseHandles, config.DatabaseFreezer, "eth/db/chaindata/", false, config.AncientRecentLimit)
|
||||
chainDb, err := stack.OpenDatabaseWithFreezer("chaindata", config.DatabaseCache, config.DatabaseHandles, config.DatabaseFreezer, "eth/db/chaindata/", false, config.AncientPrune)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -213,7 +213,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
|||
TrieTimeLimit: config.TrieTimeout,
|
||||
SnapshotLimit: config.SnapshotCache,
|
||||
Preimages: config.Preimages,
|
||||
AncientRecentLimit: config.AncientRecentLimit,
|
||||
AncientPrune: config.AncientPrune,
|
||||
}
|
||||
)
|
||||
eth.blockchain, err = core.NewBlockChainV2(chainDb, cacheConfig, chainConfig, &config.TxTrace, txStore, eth.engine, vmConfig, eth.shouldPreserve, &config.TxLookupLimit)
|
||||
|
|
@ -226,7 +226,9 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
|||
eth.blockchain.SetHead(compat.RewindTo)
|
||||
rawdb.WriteChainConfig(chainDb, genesisHash, chainConfig)
|
||||
}
|
||||
eth.bloomIndexer.Start(eth.blockchain)
|
||||
if !config.AncientPrune {
|
||||
eth.bloomIndexer.Start(eth.blockchain)
|
||||
}
|
||||
|
||||
if config.TxPool.Journal != "" {
|
||||
config.TxPool.Journal = stack.ResolvePath(config.TxPool.Journal)
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ type Config struct {
|
|||
DatabaseHandles int `toml:"-"`
|
||||
DatabaseCache int
|
||||
DatabaseFreezer string
|
||||
AncientRecentLimit uint64
|
||||
AncientPrune bool
|
||||
|
||||
TrieCleanCache int
|
||||
TrieCleanCacheJournal string `toml:",omitempty"` // Disk journal directory for trie cache to survive node restarts
|
||||
|
|
|
|||
|
|
@ -739,7 +739,7 @@ func (n *Node) OpenDatabaseWithTrace(cache, handles int, tracer, namespace strin
|
|||
// also attaching a chain freezer to it that moves ancient chain data from the
|
||||
// database to immutable append-only files. If the node is an ephemeral one, a
|
||||
// memory database is returned.
|
||||
func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, freezer, namespace string, readonly bool, ancientRecentLimit uint64) (ethdb.Database, error) {
|
||||
func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, freezer, namespace string, readonly, ancientPrune bool) (ethdb.Database, error) {
|
||||
n.lock.Lock()
|
||||
defer n.lock.Unlock()
|
||||
if n.state == closedState {
|
||||
|
|
@ -758,7 +758,7 @@ func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, freezer,
|
|||
case !filepath.IsAbs(freezer):
|
||||
freezer = n.ResolvePath(freezer)
|
||||
}
|
||||
db, err = rawdb.NewLevelDBDatabaseWithFreezer(root, cache, handles, freezer, namespace, readonly, ancientRecentLimit)
|
||||
db, err = rawdb.NewLevelDBDatabaseWithFreezer(root, cache, handles, freezer, namespace, readonly, ancientPrune)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
|
|
|
|||
Loading…
Reference in a new issue