mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-14 07:53:47 +00:00
internal/cli: add support for removedb (#478)
* internal/cli: add support for removedb * update docs * internal/cli: use constant path, handle err
This commit is contained in:
parent
16408ba324
commit
ac559bcd16
5 changed files with 170 additions and 2 deletions
|
|
@ -40,6 +40,8 @@
|
||||||
|
|
||||||
- [```peers status```](./peers_status.md)
|
- [```peers status```](./peers_status.md)
|
||||||
|
|
||||||
|
- [```removedb```](./removedb.md)
|
||||||
|
|
||||||
- [```server```](./server.md)
|
- [```server```](./server.md)
|
||||||
|
|
||||||
- [```status```](./status.md)
|
- [```status```](./status.md)
|
||||||
|
|
|
||||||
7
docs/cli/removedb.md
Normal file
7
docs/cli/removedb.md
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
# RemoveDB
|
||||||
|
|
||||||
|
The ```bor removedb``` command will remove the blockchain and state databases at the given datadir location
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
- ```datadir```: Path of the data directory to store information
|
||||||
|
|
@ -184,6 +184,11 @@ func Commands() map[string]MarkDownCommandFactory {
|
||||||
UI: ui,
|
UI: ui,
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
"removedb": func() (MarkDownCommand, error) {
|
||||||
|
return &RemoveDBCommand{
|
||||||
|
Meta2: meta2,
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
154
internal/cli/removedb.go
Normal file
154
internal/cli/removedb.go
Normal file
|
|
@ -0,0 +1,154 @@
|
||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/cli/flagset"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/cli/server"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/ethereum/go-ethereum/node"
|
||||||
|
|
||||||
|
"github.com/mitchellh/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RemoveDBCommand is for removing blockchain and state databases
|
||||||
|
type RemoveDBCommand struct {
|
||||||
|
*Meta2
|
||||||
|
|
||||||
|
datadir string
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
chaindataPath string = "chaindata"
|
||||||
|
ancientPath string = "ancient"
|
||||||
|
lightchaindataPath string = "lightchaindata"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MarkDown implements cli.MarkDown interface
|
||||||
|
func (c *RemoveDBCommand) MarkDown() string {
|
||||||
|
items := []string{
|
||||||
|
"# RemoveDB",
|
||||||
|
"The ```bor removedb``` command will remove the blockchain and state databases at the given datadir location",
|
||||||
|
c.Flags().MarkDown(),
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(items, "\n\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Help implements the cli.Command interface
|
||||||
|
func (c *RemoveDBCommand) Help() string {
|
||||||
|
return `Usage: bor removedb <datadir>
|
||||||
|
|
||||||
|
This command will remove the blockchain and state databases at the given datadir location`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Synopsis implements the cli.Command interface
|
||||||
|
func (c *RemoveDBCommand) Synopsis() string {
|
||||||
|
return "Remove blockchain and state databases"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RemoveDBCommand) Flags() *flagset.Flagset {
|
||||||
|
flags := c.NewFlagSet("removedb")
|
||||||
|
|
||||||
|
flags.StringFlag(&flagset.StringFlag{
|
||||||
|
Name: "datadir",
|
||||||
|
Value: &c.datadir,
|
||||||
|
Usage: "Path of the data directory to store information",
|
||||||
|
})
|
||||||
|
|
||||||
|
return flags
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run implements the cli.Command interface
|
||||||
|
func (c *RemoveDBCommand) Run(args []string) int {
|
||||||
|
flags := c.Flags()
|
||||||
|
|
||||||
|
// parse datadir
|
||||||
|
if err := flags.Parse(args); err != nil {
|
||||||
|
c.UI.Error(err.Error())
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
datadir := c.datadir
|
||||||
|
if datadir == "" {
|
||||||
|
datadir = server.DefaultDataDir()
|
||||||
|
}
|
||||||
|
|
||||||
|
// create ethereum node config with just the datadir
|
||||||
|
nodeCfg := &node.Config{DataDir: datadir}
|
||||||
|
|
||||||
|
// Remove the full node state database
|
||||||
|
path := nodeCfg.ResolvePath(chaindataPath)
|
||||||
|
if common.FileExist(path) {
|
||||||
|
confirmAndRemoveDB(c.UI, path, "full node state database")
|
||||||
|
} else {
|
||||||
|
log.Info("Full node state database missing", "path", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the full node ancient database
|
||||||
|
// Note: The old cli used DatabaseFreezer path from config if provided explicitly
|
||||||
|
// We don't have access to eth config and hence we assume it to be
|
||||||
|
// under the "chaindata" folder.
|
||||||
|
path = filepath.Join(nodeCfg.ResolvePath(chaindataPath), ancientPath)
|
||||||
|
if common.FileExist(path) {
|
||||||
|
confirmAndRemoveDB(c.UI, path, "full node ancient database")
|
||||||
|
} else {
|
||||||
|
log.Info("Full node ancient database missing", "path", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the light node database
|
||||||
|
path = nodeCfg.ResolvePath(lightchaindataPath)
|
||||||
|
if common.FileExist(path) {
|
||||||
|
confirmAndRemoveDB(c.UI, path, "light node database")
|
||||||
|
} else {
|
||||||
|
log.Info("Light node database missing", "path", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// confirmAndRemoveDB prompts the user for a last confirmation and removes the
|
||||||
|
// folder if accepted.
|
||||||
|
func confirmAndRemoveDB(ui cli.Ui, database string, kind string) {
|
||||||
|
for {
|
||||||
|
confirm, err := ui.Ask(fmt.Sprintf("Remove %s (%s)? [y/n]", kind, database))
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case err != nil:
|
||||||
|
ui.Output(err.Error())
|
||||||
|
return
|
||||||
|
case confirm != "":
|
||||||
|
switch strings.ToLower(confirm) {
|
||||||
|
case "y":
|
||||||
|
start := time.Now()
|
||||||
|
err = filepath.Walk(database, func(path string, info os.FileInfo, err error) error {
|
||||||
|
// If we're at the top level folder, recurse into
|
||||||
|
if path == database {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Delete all the files, but not subfolders
|
||||||
|
if !info.IsDir() {
|
||||||
|
return os.Remove(path)
|
||||||
|
}
|
||||||
|
return filepath.SkipDir
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil && err != filepath.SkipDir {
|
||||||
|
ui.Output(err.Error())
|
||||||
|
} else {
|
||||||
|
log.Info("Database successfully deleted", "path", database, "elapsed", common.PrettyDuration(time.Since(start)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
case "n":
|
||||||
|
log.Info("Database deletion skipped", "path", database)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -394,7 +394,7 @@ func DefaultConfig() *Config {
|
||||||
Identity: Hostname(),
|
Identity: Hostname(),
|
||||||
RequiredBlocks: map[string]string{},
|
RequiredBlocks: map[string]string{},
|
||||||
LogLevel: "INFO",
|
LogLevel: "INFO",
|
||||||
DataDir: defaultDataDir(),
|
DataDir: DefaultDataDir(),
|
||||||
P2P: &P2PConfig{
|
P2P: &P2PConfig{
|
||||||
MaxPeers: 30,
|
MaxPeers: 30,
|
||||||
MaxPendPeers: 50,
|
MaxPendPeers: 50,
|
||||||
|
|
@ -1040,7 +1040,7 @@ func parseBootnodes(urls []string) ([]*enode.Node, error) {
|
||||||
return dst, nil
|
return dst, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultDataDir() string {
|
func DefaultDataDir() string {
|
||||||
// Try to place the data folder in the user's home dir
|
// Try to place the data folder in the user's home dir
|
||||||
home, _ := homedir.Dir()
|
home, _ := homedir.Dir()
|
||||||
if home == "" {
|
if home == "" {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue