Skip to content

Commit

Permalink
core, cmd/utils: check ancient store path forceily
Browse files Browse the repository at this point in the history
  • Loading branch information
rjl493456442 committed Apr 29, 2019
1 parent 0de5a8d commit 639ab04
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 15 deletions.
99 changes: 84 additions & 15 deletions cmd/geth/chaincmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"runtime"
"strconv"
"sync/atomic"
Expand Down Expand Up @@ -166,6 +167,21 @@ Remove blockchain and state databases`,
The arguments are interpreted as block numbers or hashes.
Use "ethereum dump 0" to dump the genesis block.`,
}
upgradeAncientCommand = cli.Command{
Action: utils.MigrateFlags(upgradeAncient),
Name: "upgrade-ancient",
Usage: "Upgrade ancient store path forcibly",
ArgsUsage: " ",
Flags: []cli.Flag{
utils.DataDirFlag,
utils.AncientFlag,
utils.CacheFlag,
utils.TestnetFlag,
utils.RinkebyFlag,
utils.GoerliFlag,
},
Category: "BLOCKCHAIN COMMANDS",
}
inspectCommand = cli.Command{
Action: utils.MigrateFlags(inspect),
Name: "inspect",
Expand All @@ -175,7 +191,6 @@ Use "ethereum dump 0" to dump the genesis block.`,
utils.DataDirFlag,
utils.AncientFlag,
utils.CacheFlag,
utils.SyncModeFlag,
utils.TestnetFlag,
utils.RinkebyFlag,
utils.GoerliFlag,
Expand Down Expand Up @@ -433,29 +448,48 @@ func copyDb(ctx *cli.Context) error {
}

func removeDB(ctx *cli.Context) error {
stack, _ := makeConfigNode(ctx)
stack, config := makeConfigNode(ctx)

for _, name := range []string{"chaindata", "lightchaindata"} {
for i, name := range []string{"chaindata", "lightchaindata"} {
// Ensure the database exists in the first place
logger := log.New("database", name)

var (
dbdirs []string
freezer string
)
dbdir := stack.ResolvePath(name)
if !common.FileExist(dbdir) {
logger.Info("Database doesn't exist, skipping", "path", dbdir)
continue
}
// Confirm removal and execute
fmt.Println(dbdir)
confirm, err := console.Stdin.PromptConfirm("Remove this database?")
switch {
case err != nil:
utils.Fatalf("%v", err)
case !confirm:
logger.Warn("Database deletion aborted")
default:
start := time.Now()
os.RemoveAll(dbdir)
logger.Info("Database successfully deleted", "elapsed", common.PrettyDuration(time.Since(start)))
dbdirs = append(dbdirs, dbdir)
if i == 0 {
freezer = config.Eth.DatabaseFreezer
switch {
case freezer == "":
freezer = filepath.Join(dbdir, "ancient")
case !filepath.IsAbs(freezer):
freezer = config.Node.ResolvePath(freezer)
}
if common.FileExist(freezer) {
dbdirs = append(dbdirs, freezer)
}
}
for i := len(dbdirs) - 1; i >= 0; i-- {
// Confirm removal and execute
fmt.Println(dbdirs[i])
confirm, err := console.Stdin.PromptConfirm("Remove this database?")
switch {
case err != nil:
utils.Fatalf("%v", err)
case !confirm:
logger.Warn("Database deletion aborted")
default:
start := time.Now()
os.RemoveAll(dbdirs[i])
logger.Info("Database successfully deleted", "elapsed", common.PrettyDuration(time.Since(start)))
}
}
}
return nil
Expand Down Expand Up @@ -489,11 +523,46 @@ func dump(ctx *cli.Context) error {
return nil
}

func upgradeAncient(ctx *cli.Context) error {
node, config := makeConfigNode(ctx)
defer node.Close()

dbdir := config.Node.ResolvePath("chaindata")
kvdb, err := rawdb.NewLevelDBDatabase(dbdir, 128, 1024, "")
if err != nil {
return err
}
defer kvdb.Close()

freezer := config.Eth.DatabaseFreezer
switch {
case freezer == "":
freezer = filepath.Join(dbdir, "ancient")
case !filepath.IsAbs(freezer):
freezer = config.Node.ResolvePath(freezer)
}
stored := rawdb.ReadAncientPath(kvdb)
if stored != freezer {
confirm, err := console.Stdin.PromptConfirm(fmt.Sprintf("Are you sure to upgrade ancient path? old:%s, new:%s", stored, freezer))
switch {
case err != nil:
utils.Fatalf("%v", err)
case !confirm:
log.Warn("Ancient path upgrade aborted")
default:
rawdb.WriteAncientPath(kvdb, freezer)
log.Info("Ancient path successfully upgraded")
}
}
return nil
}

func inspect(ctx *cli.Context) error {
node, _ := makeConfigNode(ctx)
defer node.Close()

_, chainDb := utils.MakeChain(ctx, node)
defer chainDb.Close()

// Spawn a goroutine to print some user-friendly logs.
stopCh := make(chan struct{})
Expand Down
1 change: 1 addition & 0 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ func init() {
copydbCommand,
removedbCommand,
dumpCommand,
upgradeAncientCommand,
inspectCommand,
// See accountcmd.go:
accountCommand,
Expand Down
2 changes: 2 additions & 0 deletions cmd/utils/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,8 @@ func ExportPreimages(db ethdb.Database, fn string) error {
}
// Iterate over the preimages and export them
it := db.NewIteratorWithPrefix([]byte("secure-key-"))
defer it.Release()

for it.Next() {
if err := rlp.Encode(writer, it.Value()); err != nil {
return err
Expand Down
14 changes: 14 additions & 0 deletions core/rawdb/accessors_metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,20 @@ func WriteChainConfig(db ethdb.KeyValueWriter, hash common.Hash, cfg *params.Cha
}
}

// ReadAncientPath retrieves ancient database path which is recorded during the
// first node setup or forcibly changed by user.
func ReadAncientPath(db ethdb.KeyValueReader) string {
data, _ := db.Get(ancientKey)
return string(data)
}

// WriteAncientPath writes ancient database path into the key-value database.
func WriteAncientPath(db ethdb.KeyValueWriter, path string) {
if err := db.Put(ancientKey, []byte(path)); err != nil {
log.Crit("Failed to store ancient path", "err", err)
}
}

// ReadPreimage retrieves a single preimage of the provided hash.
func ReadPreimage(db ethdb.KeyValueReader, hash common.Hash) []byte {
data, _ := db.Get(preimageKey(hash))
Expand Down
15 changes: 15 additions & 0 deletions core/rawdb/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethdb/leveldb"
"github.com/ethereum/go-ethereum/ethdb/memorydb"
"github.com/ethereum/go-ethereum/log"
"github.com/olekukonko/tablewriter"
)

Expand Down Expand Up @@ -149,6 +150,20 @@ func NewLevelDBDatabaseWithFreezer(file string, cache int, handles int, freezer
kvdb.Close()
return nil, err
}
// Make sure we always use the same ancient store.
//
// stored == nil stored != nil
// +------------------------------------------------
// freezer == nil | non-freezer mode | ancient store is missing
// freezer != nil | initialize | ensure consistency
stored := ReadAncientPath(kvdb)
if stored == "" && freezer != "" {
WriteAncientPath(kvdb, freezer)
log.Info("Record initial ancient path", "path", freezer)
} else if stored != freezer {
log.Warn("Ancient store mismatch", "stored", stored, "given", freezer)
log.Crit("Please use a consistent ancient path or modify it via the command line tool `geth upgrade-ancient`")
}
return frdb, nil
}

Expand Down
1 change: 1 addition & 0 deletions core/rawdb/freezer.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ func newFreezer(datadir string, namespace string) (*freezer, error) {
lock.Release()
return nil, err
}
log.Info("Open freezer as ancient database", "path", datadir)
return freezer, nil
}

Expand Down
1 change: 1 addition & 0 deletions core/rawdb/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ var (

preimagePrefix = []byte("secure-key-") // preimagePrefix + hash -> preimage
configPrefix = []byte("ethereum-config-") // config prefix for the db
ancientKey = []byte("ancient-path-") // ancient database path

// Chain index prefixes (use `i` + single byte to avoid mixing data types).
BloomBitsIndexPrefix = []byte("iB") // BloomBitsIndexPrefix is the data table of a chain indexer to track its progress
Expand Down

0 comments on commit 639ab04

Please sign in to comment.