forked from maticnetwork/bor
/
removedb.go
154 lines (128 loc) · 3.88 KB
/
removedb.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
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
}
}
}
}