cmd/geth: add db-command to inspect freezer index (#22633)

This PR makes it easier to inspect the freezer index, which could be useful to investigate things like #22111
This commit is contained in:
Martin Holst Swende 2021-04-13 15:45:30 +02:00 committed by GitHub
parent 6c27d8f996
commit 271e5b7fc9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 72 additions and 15 deletions

View File

@ -20,6 +20,7 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"sort"
"strconv" "strconv"
"time" "time"
@ -60,6 +61,7 @@ Remove blockchain and state databases`,
dbDeleteCmd, dbDeleteCmd,
dbPutCmd, dbPutCmd,
dbGetSlotsCmd, dbGetSlotsCmd,
dbDumpFreezerIndex,
}, },
} }
dbInspectCmd = cli.Command{ dbInspectCmd = cli.Command{
@ -177,6 +179,22 @@ WARNING: This is a low-level operation which may cause database corruption!`,
}, },
Description: "This command looks up the specified database key from the database.", Description: "This command looks up the specified database key from the database.",
} }
dbDumpFreezerIndex = cli.Command{
Action: utils.MigrateFlags(freezerInspect),
Name: "freezer-index",
Usage: "Dump out the index of a given freezer type",
ArgsUsage: "<type> <start (int)> <end (int)>",
Flags: []cli.Flag{
utils.DataDirFlag,
utils.SyncModeFlag,
utils.MainnetFlag,
utils.RopstenFlag,
utils.RinkebyFlag,
utils.GoerliFlag,
utils.YoloV3Flag,
},
Description: "This command displays information about the freezer index.",
}
) )
func removeDB(ctx *cli.Context) error { func removeDB(ctx *cli.Context) error {
@ -449,3 +467,43 @@ func dbDumpTrie(ctx *cli.Context) error {
} }
return it.Err return it.Err
} }
func freezerInspect(ctx *cli.Context) error {
var (
start, end int64
disableSnappy bool
err error
)
if ctx.NArg() < 3 {
return fmt.Errorf("required arguments: %v", ctx.Command.ArgsUsage)
}
kind := ctx.Args().Get(0)
if noSnap, ok := rawdb.FreezerNoSnappy[kind]; !ok {
var options []string
for opt := range rawdb.FreezerNoSnappy {
options = append(options, opt)
}
sort.Strings(options)
return fmt.Errorf("Could read freezer-type '%v'. Available options: %v", kind, options)
} else {
disableSnappy = noSnap
}
if start, err = strconv.ParseInt(ctx.Args().Get(1), 10, 64); err != nil {
log.Info("Could read start-param", "error", err)
return err
}
if end, err = strconv.ParseInt(ctx.Args().Get(2), 10, 64); err != nil {
log.Info("Could read count param", "error", err)
return err
}
stack, _ := makeConfigNode(ctx)
defer stack.Close()
path := filepath.Join(stack.ResolvePath("chaindata"), "ancient")
log.Info("Opening freezer", "location", path, "name", kind)
if f, err := rawdb.NewFreezerTable(path, kind, disableSnappy); err != nil {
return err
} else {
f.DumpIndex(start, end)
}
return nil
}

View File

@ -118,7 +118,7 @@ func newFreezer(datadir string, namespace string, readonly bool) (*freezer, erro
trigger: make(chan chan struct{}), trigger: make(chan chan struct{}),
quit: make(chan struct{}), quit: make(chan struct{}),
} }
for name, disableSnappy := range freezerNoSnappy { for name, disableSnappy := range FreezerNoSnappy {
table, err := newTable(datadir, name, readMeter, writeMeter, sizeGauge, disableSnappy) table, err := newTable(datadir, name, readMeter, writeMeter, sizeGauge, disableSnappy)
if err != nil { if err != nil {
for _, table := range freezer.tables { for _, table := range freezer.tables {

View File

@ -636,25 +636,24 @@ func (t *freezerTable) Sync() error {
return t.head.Sync() return t.head.Sync()
} }
// printIndex is a debug print utility function for testing // DumpIndex is a debug print utility function, mainly for testing. It can also
func (t *freezerTable) printIndex() { // be used to analyse a live freezer table index.
func (t *freezerTable) DumpIndex(start, stop int64) {
buf := make([]byte, indexEntrySize) buf := make([]byte, indexEntrySize)
fmt.Printf("|-----------------|\n") fmt.Printf("| number | fileno | offset |\n")
fmt.Printf("| fileno | offset |\n") fmt.Printf("|--------|--------|--------|\n")
fmt.Printf("|--------+--------|\n")
for i := uint64(0); ; i++ { for i := uint64(start); ; i++ {
if _, err := t.index.ReadAt(buf, int64(i*indexEntrySize)); err != nil { if _, err := t.index.ReadAt(buf, int64(i*indexEntrySize)); err != nil {
break break
} }
var entry indexEntry var entry indexEntry
entry.unmarshalBinary(buf) entry.unmarshalBinary(buf)
fmt.Printf("| %03d | %03d | \n", entry.filenum, entry.offset) fmt.Printf("| %03d | %03d | %03d | \n", i, entry.filenum, entry.offset)
if i > 100 { if stop > 0 && i >= uint64(stop) {
fmt.Printf(" ... \n")
break break
} }
} }
fmt.Printf("|-----------------|\n") fmt.Printf("|--------------------------|\n")
} }

View File

@ -525,7 +525,7 @@ func TestOffset(t *testing.T) {
f.Append(4, getChunk(20, 0xbb)) f.Append(4, getChunk(20, 0xbb))
f.Append(5, getChunk(20, 0xaa)) f.Append(5, getChunk(20, 0xaa))
f.printIndex() f.DumpIndex(0, 100)
f.Close() f.Close()
} }
// Now crop it. // Now crop it.
@ -572,7 +572,7 @@ func TestOffset(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
f.printIndex() f.DumpIndex(0, 100)
// It should allow writing item 6 // It should allow writing item 6
f.Append(numDeleted+2, getChunk(20, 0x99)) f.Append(numDeleted+2, getChunk(20, 0x99))

View File

@ -114,9 +114,9 @@ const (
freezerDifficultyTable = "diffs" freezerDifficultyTable = "diffs"
) )
// freezerNoSnappy configures whether compression is disabled for the ancient-tables. // FreezerNoSnappy configures whether compression is disabled for the ancient-tables.
// Hashes and difficulties don't compress well. // Hashes and difficulties don't compress well.
var freezerNoSnappy = map[string]bool{ var FreezerNoSnappy = map[string]bool{
freezerHeaderTable: false, freezerHeaderTable: false,
freezerHashTable: true, freezerHashTable: true,
freezerBodiesTable: false, freezerBodiesTable: false,