diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 12524bee5a..10c1be58b7 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -504,7 +504,7 @@ var ( } PruneAncientDataFlag = cli.BoolFlag{ Name: "pruneancient", - Usage: "Prune ancient data, recommends to the user who don't care about the ancient data. Note that once be turned on, the ancient data will not be recovered again", + Usage: "Prune ancient data, is an optional config and disabled by default. Only keep the latest 9w blocks' data,the older blocks' data will be permanently pruned. Notice:the geth/chaindata/ancient dir will be removed, if restart without the flag, the ancient data will start with the previous point that the oldest unpruned block number. Recommends to the user who don't care about the ancient data.", } // Miner settings MiningEnabledFlag = cli.BoolFlag{ diff --git a/core/rawdb/database.go b/core/rawdb/database.go index da37aeee48..f63112f313 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -191,8 +191,16 @@ func NewFreezerDb(db ethdb.KeyValueStore, frz, namespace string, readonly bool, // value data store with a freezer moving immutable chain segments into cold // storage. func NewDatabaseWithFreezer(db ethdb.KeyValueStore, freezer string, namespace string, readonly, disableFreeze, isLastOffset, pruneAncientData, skipCheckFreezerType bool) (ethdb.Database, error) { + var offset uint64 + // The offset of ancientDB should be handled differently in different scenarios. + if isLastOffset { + offset = ReadOffSetOfLastAncientFreezer(db) + } else { + offset = ReadOffSetOfCurrentAncientFreezer(db) + } + if pruneAncientData && !disableFreeze && !readonly { - frdb, err := newPrunedFreezer(freezer, db) + frdb, err := newPrunedFreezer(freezer, db, offset) if err != nil { return nil, err } @@ -211,17 +219,8 @@ func NewDatabaseWithFreezer(db ethdb.KeyValueStore, freezer string, namespace st log.Error("pruneancient not take effect, disableFreezer or readonly be set") } - if !skipCheckFreezerType && ReadAncientType(db) == PruneFreezerType { - log.Warn("prune ancinet flag is set, may start fail, can add pruneancient parameter resolve") - return nil, errors.New("pruneancient was set, please add pruneancient parameter") - } - - var offset uint64 - // The offset of ancientDB should be handled differently in different scenarios. - if isLastOffset { - offset = ReadOffSetOfLastAncientFreezer(db) - } else { - offset = ReadOffSetOfCurrentAncientFreezer(db) + if prunedFrozen := ReadFrozenOfAncientFreezer(db); prunedFrozen > offset { + offset = prunedFrozen } // Create the idle freezer instance diff --git a/core/rawdb/prunedfreezer.go b/core/rawdb/prunedfreezer.go index 3896dd5935..becef3fc93 100644 --- a/core/rawdb/prunedfreezer.go +++ b/core/rawdb/prunedfreezer.go @@ -30,7 +30,7 @@ type prunedfreezer struct { } // newNoDataFreezer creates a chain freezer that deletes data enough ‘old’. -func newPrunedFreezer(datadir string, db ethdb.KeyValueStore) (*prunedfreezer, error) { +func newPrunedFreezer(datadir string, db ethdb.KeyValueStore, offset uint64) (*prunedfreezer, error) { if info, err := os.Lstat(datadir); !os.IsNotExist(err) { if info.Mode()&os.ModeSymlink != 0 { log.Warn("Symbolic link ancient database is not supported", "path", datadir) @@ -45,6 +45,7 @@ func newPrunedFreezer(datadir string, db ethdb.KeyValueStore) (*prunedfreezer, e freezer := &prunedfreezer{ db: db, + frozen: offset, threshold: params.FullImmutabilityThreshold, instanceLock: lock, quit: make(chan struct{}), @@ -54,16 +55,18 @@ func newPrunedFreezer(datadir string, db ethdb.KeyValueStore) (*prunedfreezer, e return nil, err } + // delete ancient dir + if err := os.RemoveAll(datadir); err != nil && !os.IsNotExist(err) { + log.Warn("remove the ancient dir failed.", "path", datadir, "error", err) + return nil, err + } log.Info("Opened ancientdb with nodata mode", "database", datadir, "frozen", freezer.frozen) return freezer, nil } // repair init frozen , compatible disk-ancientdb and pruner-block-tool. func (f *prunedfreezer) repair(datadir string) error { - // compatible prune-block-tool - offset := ReadOffSetOfCurrentAncientFreezer(f.db) - log.Info("Read last offline prune-block start block number", "offset", offset) - + offset := atomic.LoadUint64(&f.frozen) // compatible freezer min := uint64(math.MaxUint64) for name, disableSnappy := range FreezerNoSnappy { @@ -167,6 +170,8 @@ func (f *prunedfreezer) TruncateAncients(items uint64) error { // Sync flushes meta data tables to disk. func (f *prunedfreezer) Sync() error { WriteFrozenOfAncientFreezer(f.db, atomic.LoadUint64(&f.frozen)) + // compatible offline prune blocks tool + WriteOffSetOfCurrentAncientFreezer(f.db, atomic.LoadUint64(&f.frozen)) return nil } diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 00717bcfba..8d032260a7 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -181,7 +181,14 @@ type Config struct { DatabaseDiff string PersistDiff bool DiffBlock uint64 - PruneAncientData bool + // PruneAncientData is an optional config and disabled by default, and usually you do not need it. + // When this flag is enabled, only keep the latest 9w blocks' data, the older blocks' data will be + // pruned instead of being dumped to freezerdb, the pruned data includes CanonicalHash, Header, Block, + // Receipt and TotalDifficulty. + // Notice: the PruneAncientData once be turned on, the get/chaindata/ancient dir will be removed, + // if restart without the pruneancient flag, the ancient data will start with the previous point that + // the oldest unpruned block number. + PruneAncientData bool TrieCleanCache int TrieCleanCacheJournal string `toml:",omitempty"` // Disk journal directory for trie cache to survive node restarts