mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-16 08:53:46 +00:00
Merge branch 'ethereum:master' into master
This commit is contained in:
commit
19f718f6e9
5 changed files with 94 additions and 61 deletions
|
|
@ -198,60 +198,73 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
func removeDB(ctx *cli.Context) error {
|
func removeDB(ctx *cli.Context) error {
|
||||||
stack, config := makeConfigNode(ctx)
|
stack, config := makeConfigNode(ctx)
|
||||||
|
|
||||||
// Remove the full node state database
|
// Resolve folder paths.
|
||||||
path := stack.ResolvePath("chaindata")
|
var (
|
||||||
if common.FileExist(path) {
|
rootDir = stack.ResolvePath("chaindata")
|
||||||
confirmAndRemoveDB(path, "full node state database")
|
ancientDir = config.Eth.DatabaseFreezer
|
||||||
} else {
|
)
|
||||||
log.Info("Full node state database missing", "path", path)
|
|
||||||
}
|
|
||||||
// Remove the full node ancient database
|
|
||||||
path = config.Eth.DatabaseFreezer
|
|
||||||
switch {
|
switch {
|
||||||
case path == "":
|
case ancientDir == "":
|
||||||
path = filepath.Join(stack.ResolvePath("chaindata"), "ancient")
|
ancientDir = filepath.Join(stack.ResolvePath("chaindata"), "ancient")
|
||||||
case !filepath.IsAbs(path):
|
case !filepath.IsAbs(ancientDir):
|
||||||
path = config.Node.ResolvePath(path)
|
ancientDir = config.Node.ResolvePath(ancientDir)
|
||||||
}
|
|
||||||
if common.FileExist(path) {
|
|
||||||
confirmAndRemoveDB(path, "full node ancient database")
|
|
||||||
} else {
|
|
||||||
log.Info("Full node ancient database missing", "path", path)
|
|
||||||
}
|
|
||||||
// Remove the light node database
|
|
||||||
path = stack.ResolvePath("lightchaindata")
|
|
||||||
if common.FileExist(path) {
|
|
||||||
confirmAndRemoveDB(path, "light node database")
|
|
||||||
} else {
|
|
||||||
log.Info("Light node database missing", "path", path)
|
|
||||||
}
|
}
|
||||||
|
// Delete state data
|
||||||
|
statePaths := []string{rootDir, filepath.Join(ancientDir, rawdb.StateFreezerName)}
|
||||||
|
confirmAndRemoveDB(statePaths, "state data")
|
||||||
|
|
||||||
|
// Delete ancient chain
|
||||||
|
chainPaths := []string{filepath.Join(ancientDir, rawdb.ChainFreezerName)}
|
||||||
|
confirmAndRemoveDB(chainPaths, "ancient chain")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// removeFolder deletes all files (not folders) inside the directory 'dir' (but
|
||||||
|
// not files in subfolders).
|
||||||
|
func removeFolder(dir string) {
|
||||||
|
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||||
|
// If we're at the top level folder, recurse into
|
||||||
|
if path == dir {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Delete all the files, but not subfolders
|
||||||
|
if !info.IsDir() {
|
||||||
|
os.Remove(path)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return filepath.SkipDir
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// confirmAndRemoveDB prompts the user for a last confirmation and removes the
|
// confirmAndRemoveDB prompts the user for a last confirmation and removes the
|
||||||
// folder if accepted.
|
// list of folders if accepted.
|
||||||
func confirmAndRemoveDB(database string, kind string) {
|
func confirmAndRemoveDB(paths []string, kind string) {
|
||||||
confirm, err := prompt.Stdin.PromptConfirm(fmt.Sprintf("Remove %s (%s)?", kind, database))
|
msg := fmt.Sprintf("Location(s) of '%s': \n", kind)
|
||||||
|
for _, path := range paths {
|
||||||
|
msg += fmt.Sprintf("\t- %s\n", path)
|
||||||
|
}
|
||||||
|
fmt.Println(msg)
|
||||||
|
|
||||||
|
confirm, err := prompt.Stdin.PromptConfirm(fmt.Sprintf("Remove '%s'?", kind))
|
||||||
switch {
|
switch {
|
||||||
case err != nil:
|
case err != nil:
|
||||||
utils.Fatalf("%v", err)
|
utils.Fatalf("%v", err)
|
||||||
case !confirm:
|
case !confirm:
|
||||||
log.Info("Database deletion skipped", "path", database)
|
log.Info("Database deletion skipped", "kind", kind, "paths", paths)
|
||||||
default:
|
default:
|
||||||
start := time.Now()
|
var (
|
||||||
filepath.Walk(database, func(path string, info os.FileInfo, err error) error {
|
deleted []string
|
||||||
// If we're at the top level folder, recurse into
|
start = time.Now()
|
||||||
if path == database {
|
)
|
||||||
return nil
|
for _, path := range paths {
|
||||||
|
if common.FileExist(path) {
|
||||||
|
removeFolder(path)
|
||||||
|
deleted = append(deleted, path)
|
||||||
|
} else {
|
||||||
|
log.Info("Folder is not existent", "path", path)
|
||||||
}
|
}
|
||||||
// Delete all the files, but not subfolders
|
}
|
||||||
if !info.IsDir() {
|
log.Info("Database successfully deleted", "kind", kind, "paths", deleted, "elapsed", common.PrettyDuration(time.Since(start)))
|
||||||
os.Remove(path)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return filepath.SkipDir
|
|
||||||
})
|
|
||||||
log.Info("Database successfully deleted", "path", database, "elapsed", common.PrettyDuration(time.Since(start)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,14 +68,14 @@ var stateFreezerNoSnappy = map[string]bool{
|
||||||
|
|
||||||
// The list of identifiers of ancient stores.
|
// The list of identifiers of ancient stores.
|
||||||
var (
|
var (
|
||||||
chainFreezerName = "chain" // the folder name of chain segment ancient store.
|
ChainFreezerName = "chain" // the folder name of chain segment ancient store.
|
||||||
stateFreezerName = "state" // the folder name of reverse diff ancient store.
|
StateFreezerName = "state" // the folder name of reverse diff ancient store.
|
||||||
)
|
)
|
||||||
|
|
||||||
// freezers the collections of all builtin freezers.
|
// freezers the collections of all builtin freezers.
|
||||||
var freezers = []string{chainFreezerName, stateFreezerName}
|
var freezers = []string{ChainFreezerName, StateFreezerName}
|
||||||
|
|
||||||
// NewStateFreezer initializes the freezer for state history.
|
// NewStateFreezer initializes the freezer for state history.
|
||||||
func NewStateFreezer(ancientDir string, readOnly bool) (*ResettableFreezer, error) {
|
func NewStateFreezer(ancientDir string, readOnly bool) (*ResettableFreezer, error) {
|
||||||
return NewResettableFreezer(filepath.Join(ancientDir, stateFreezerName), "eth/db/state", readOnly, stateHistoryTableSize, stateFreezerNoSnappy)
|
return NewResettableFreezer(filepath.Join(ancientDir, StateFreezerName), "eth/db/state", readOnly, stateHistoryTableSize, stateFreezerNoSnappy)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,14 +81,14 @@ func inspectFreezers(db ethdb.Database) ([]freezerInfo, error) {
|
||||||
var infos []freezerInfo
|
var infos []freezerInfo
|
||||||
for _, freezer := range freezers {
|
for _, freezer := range freezers {
|
||||||
switch freezer {
|
switch freezer {
|
||||||
case chainFreezerName:
|
case ChainFreezerName:
|
||||||
info, err := inspect(chainFreezerName, chainFreezerNoSnappy, db)
|
info, err := inspect(ChainFreezerName, chainFreezerNoSnappy, db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
infos = append(infos, info)
|
infos = append(infos, info)
|
||||||
|
|
||||||
case stateFreezerName:
|
case StateFreezerName:
|
||||||
if ReadStateScheme(db) != PathScheme {
|
if ReadStateScheme(db) != PathScheme {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -102,7 +102,7 @@ func inspectFreezers(db ethdb.Database) ([]freezerInfo, error) {
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
info, err := inspect(stateFreezerName, stateFreezerNoSnappy, f)
|
info, err := inspect(StateFreezerName, stateFreezerNoSnappy, f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -125,9 +125,9 @@ func InspectFreezerTable(ancient string, freezerName string, tableName string, s
|
||||||
tables map[string]bool
|
tables map[string]bool
|
||||||
)
|
)
|
||||||
switch freezerName {
|
switch freezerName {
|
||||||
case chainFreezerName:
|
case ChainFreezerName:
|
||||||
path, tables = resolveChainFreezerDir(ancient), chainFreezerNoSnappy
|
path, tables = resolveChainFreezerDir(ancient), chainFreezerNoSnappy
|
||||||
case stateFreezerName:
|
case StateFreezerName:
|
||||||
path, tables = filepath.Join(ancient, freezerName), stateFreezerNoSnappy
|
path, tables = filepath.Join(ancient, freezerName), stateFreezerNoSnappy
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown freezer, supported ones: %v", freezers)
|
return fmt.Errorf("unknown freezer, supported ones: %v", freezers)
|
||||||
|
|
|
||||||
|
|
@ -178,7 +178,7 @@ func resolveChainFreezerDir(ancient string) string {
|
||||||
// sub folder, if not then two possibilities:
|
// sub folder, if not then two possibilities:
|
||||||
// - chain freezer is not initialized
|
// - chain freezer is not initialized
|
||||||
// - chain freezer exists in legacy location (root ancient folder)
|
// - chain freezer exists in legacy location (root ancient folder)
|
||||||
freezer := path.Join(ancient, chainFreezerName)
|
freezer := path.Join(ancient, ChainFreezerName)
|
||||||
if !common.FileExist(freezer) {
|
if !common.FileExist(freezer) {
|
||||||
if !common.FileExist(ancient) {
|
if !common.FileExist(ancient) {
|
||||||
// The entire ancient store is not initialized, still use the sub
|
// The entire ancient store is not initialized, still use the sub
|
||||||
|
|
|
||||||
|
|
@ -170,14 +170,31 @@ func New(diskdb ethdb.Database, config *Config) *Database {
|
||||||
}
|
}
|
||||||
db.freezer = freezer
|
db.freezer = freezer
|
||||||
|
|
||||||
// Truncate the extra state histories above in freezer in case
|
diskLayerID := db.tree.bottom().stateID()
|
||||||
// it's not aligned with the disk layer.
|
if diskLayerID == 0 {
|
||||||
pruned, err := truncateFromHead(db.diskdb, freezer, db.tree.bottom().stateID())
|
// Reset the entire state histories in case the trie database is
|
||||||
if err != nil {
|
// not initialized yet, as these state histories are not expected.
|
||||||
log.Crit("Failed to truncate extra state histories", "err", err)
|
frozen, err := db.freezer.Ancients()
|
||||||
}
|
if err != nil {
|
||||||
if pruned != 0 {
|
log.Crit("Failed to retrieve head of state history", "err", err)
|
||||||
log.Warn("Truncated extra state histories", "number", pruned)
|
}
|
||||||
|
if frozen != 0 {
|
||||||
|
err := db.freezer.Reset()
|
||||||
|
if err != nil {
|
||||||
|
log.Crit("Failed to reset state histories", "err", err)
|
||||||
|
}
|
||||||
|
log.Info("Truncated extraneous state history")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Truncate the extra state histories above in freezer in case
|
||||||
|
// it's not aligned with the disk layer.
|
||||||
|
pruned, err := truncateFromHead(db.diskdb, freezer, diskLayerID)
|
||||||
|
if err != nil {
|
||||||
|
log.Crit("Failed to truncate extra state histories", "err", err)
|
||||||
|
}
|
||||||
|
if pruned != 0 {
|
||||||
|
log.Warn("Truncated extra state histories", "number", pruned)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Disable database in case node is still in the initial state sync stage.
|
// Disable database in case node is still in the initial state sync stage.
|
||||||
|
|
@ -431,6 +448,9 @@ func (db *Database) Initialized(genesisRoot common.Hash) bool {
|
||||||
inited = true
|
inited = true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
if !inited {
|
||||||
|
inited = rawdb.ReadSnapSyncStatusFlag(db.diskdb) != rawdb.StateSyncUnknown
|
||||||
|
}
|
||||||
return inited
|
return inited
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue