Skip to content
This repository was archived by the owner on Aug 13, 2019. It is now read-only.

Commit b474a40

Browse files
author
Krasi Georgiev
committed
refactored and use printBlock for prety display
Signed-off-by: Krasi Georgiev <[email protected]>
1 parent 24acade commit b474a40

File tree

2 files changed

+99
-66
lines changed

2 files changed

+99
-66
lines changed

cmd/tsdb/main.go

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ func main() {
4949
listCmdHumanReadable = listCmd.Flag("human-readable", "print human readable values").Short('h').Bool()
5050
listPath = listCmd.Arg("db path", "database path (default is benchout/storage)").Default("benchout/storage").String()
5151
scanCmd = cli.Command("scan", "scans the db and lists corrupted blocks")
52+
scanCmdHumanReadable = scanCmd.Flag("human-readable", "print human readable values").Short('h').Bool()
5253
scanPath = scanCmd.Arg("dir", "database path (default is current dir ./)").Default("./").ExistingDir()
5354
)
5455

@@ -60,15 +61,16 @@ func main() {
6061
samplesFile: *benchSamplesFile,
6162
}
6263
wb.run()
64+
6365
case listCmd.FullCommand():
6466
db, err := tsdb.Open(*listPath, nil, nil, nil)
6567
if err != nil {
6668
exitWithError(err)
6769
}
6870
printBlocks(db.Blocks(), listCmdHumanReadable)
69-
case scanCmd.FullCommand():
7071

71-
// Scan for temporary files.
72+
case scanCmd.FullCommand():
73+
fmt.Println("Scanning for temporary files...")
7274
var tmpFiles []string
7375
filepath.Walk(*scanPath, func(path string, f os.FileInfo, _ error) error {
7476
if !f.IsDir() {
@@ -80,48 +82,40 @@ func main() {
8082
})
8183
if len(tmpFiles) > 0 {
8284
fmt.Println(`
83-
Scanning found some temporary files!
8485
These are usually caused by a crash or incomplete compaction and
85-
are safe to delete as long as you are sure that no other application is currently using this database folder.`)
86+
are safe to delete as long as you are sure that no other application is currently using this database.`)
8687

87-
promptDelete(tmpFiles)
88+
promptDelete(tmpFiles, scanCmdHumanReadable)
8889

8990
}
9091

91-
useless, err := tsdb.Scan(*scanPath)
92+
scanner, err := tsdb.NewDBScanner(*scanPath)
9293
if err != nil {
9394
exitWithError(err)
9495
}
9596

96-
if len(useless) == 0 {
97-
fmt.Println("Hooray! The db has no corrupted blocks (or the scan tool is broken).\U0001f638")
98-
return
99-
}
100-
101-
for err, paths := range useless {
102-
fmt.Println(err)
103-
for _, path := range paths {
104-
fmt.Println(path)
105-
}
106-
switch err.(type) {
107-
case tsdb.ErrorOpen:
108-
fmt.Println(`
109-
Scanning found some blocks that cannot be opened!
110-
Deleting these will allow a clean startup, but you will loose all data in the listed time ranges.`)
111-
case tsdb.ErrorSequence:
112-
fmt.Println(`
113-
Scanning found some overlapping blocks!
114-
Deleting these will allow a clean startup, but you will loose all data in the listed time ranges.`)
115-
}
116-
117-
promptDelete(paths)
97+
for err, useless := range scanner.Scan() {
98+
fmt.Printf("Deleting these will loose all data in the listed time ranges.%v", err)
99+
promptDelete(useless, scanCmdHumanReadable)
118100
}
119101
}
120102
flag.CommandLine.Set("log.level", "debug")
121103
}
122104

123-
func promptDelete(paths []string) {
124-
fmt.Println(paths)
105+
func promptDelete(i interface{}, humanReadable *bool) {
106+
var paths []string
107+
switch i.(type) {
108+
case []*tsdb.Block:
109+
blocks := i.([]*tsdb.Block)
110+
for _, b := range blocks {
111+
paths = append(paths, b.Dir())
112+
}
113+
printBlocks(blocks, humanReadable)
114+
case []string:
115+
paths = i.([]string)
116+
printTmps(paths, humanReadable)
117+
}
118+
125119
fmt.Printf("Do you want to delete these (y/N)? ")
126120
var s string
127121
_, err := fmt.Scanln(&s)
@@ -144,7 +138,7 @@ func promptDelete(paths []string) {
144138
return
145139
}
146140
fmt.Printf("%v is not a valid answer \n", s)
147-
promptDelete(paths)
141+
promptDelete(i, humanReadable)
148142
}
149143

150144
type writeBenchmark struct {
@@ -425,6 +419,11 @@ func exitWithError(err error) {
425419
os.Exit(1)
426420
}
427421

422+
func printTmps(tmps []string, humanReadable *bool) {
423+
424+
fmt.Println(tmps)
425+
}
426+
428427
func printBlocks(blocks []*tsdb.Block, humanReadable *bool) {
429428
tw := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
430429
defer tw.Flush()

scan.go

Lines changed: 69 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,59 +2,93 @@ package tsdb
22

33
import (
44
"fmt"
5+
"path/filepath"
56

67
"github.com/pkg/errors"
8+
"github.com/prometheus/tsdb/chunks"
9+
"github.com/prometheus/tsdb/index"
710
)
811

9-
type ErrorOpen string
10-
11-
func (e ErrorOpen) Error() string {
12-
return fmt.Sprintf("block open error: %v", e)
12+
type DBScanner struct {
13+
db *DB
14+
dirs []string
1315
}
1416

15-
type ErrorSequence string
16-
17-
func (e ErrorSequence) Error() string {
18-
return fmt.Sprintf("block sequence error %v", e)
19-
}
17+
func NewDBScanner(dir string) (*DBScanner, error) {
2018

21-
// Scan checks the integrity of the tsdb for a given directory and returns a list of files and folders that can be deleted.
22-
// It returns a map of error to explain the reason and slice of dirs for further processing.
23-
func Scan(dir string) (map[error][]string, error) {
24-
useless := make(map[error][]string)
25-
26-
db := &DB{
27-
dir: dir,
28-
logger: nil,
29-
opts: &Options{},
19+
dbScanner := &DBScanner{
20+
db: &DB{
21+
dir: dir,
22+
logger: nil,
23+
opts: &Options{},
24+
},
3025
}
3126

32-
dirs, err := blockDirs(db.dir)
27+
dirs, err := blockDirs(dir)
3328
if err != nil {
34-
return nil, errors.Wrap(err, "find blocks")
29+
return nil, err
3530
}
31+
dbScanner.dirs = dirs
32+
return dbScanner, nil
33+
}
3634

37-
// Scan for blocks that can't be opened.
38-
var errOpen ErrorOpen
39-
for _, dir := range dirs {
40-
b, err := OpenBlock(dir, nil)
41-
if err != nil {
42-
errOpen = ErrorOpen(err.Error())
43-
useless[errOpen] = append(useless[errOpen], dir)
35+
// Scan checks the integrity of the tsdb and returns a slice of blocks that return an error while processing.
36+
// The blocks are grouped in a map by the error.
37+
func (db *DBScanner) Scan() map[error][]*Block {
38+
39+
uselessBlocks := make(map[error][]*Block)
40+
var goodBlocks []*Block
41+
42+
for _, dir := range db.dirs {
43+
var err error
44+
block := &Block{
45+
dir: dir,
46+
}
47+
for {
48+
meta, err := readMetaFile(dir)
49+
if err != nil {
50+
err = errors.Wrap(err, "reading block meta")
51+
break
52+
}
53+
block.meta = *meta
54+
55+
if block.chunkr, err = chunks.NewDirReader(chunkDir(dir), nil); err != nil {
56+
err = errors.Wrap(err, "reading block chunk")
57+
break
58+
}
59+
60+
if block.indexr, err = index.NewFileReader(filepath.Join(dir, "index")); err != nil {
61+
err = errors.Wrap(err, "reading block index")
62+
break
63+
}
64+
65+
if block.tombstones, err = readTombstones(dir); err != nil {
66+
err = errors.Wrap(err, "reading block tumbstone")
67+
break
68+
}
4469
break
4570
}
4671

47-
db.blocks = append(db.blocks, b)
72+
if err != nil {
73+
uselessBlocks[err] = append(uselessBlocks[err], block)
74+
} else {
75+
goodBlocks = append(goodBlocks, block)
76+
}
77+
4878
}
4979

5080
// Scan for overlaping blocks.
51-
if overlaps := validateBlockSequence(db.blocks); overlaps != nil {
52-
var dirs []string
53-
for _, b := range db.blocks {
54-
dirs = append(dirs, b.Dir())
81+
for time, overlappingMetas := range validateBlockSequence(goodBlocks) {
82+
err := fmt.Errorf("overlapping blocks range: %v , %v", time.Min, time.Min)
83+
for _, m := range overlappingMetas {
84+
for _, b := range goodBlocks {
85+
if m.ULID == b.Meta().ULID {
86+
uselessBlocks[err] = append(uselessBlocks[err], b)
87+
break
88+
}
89+
}
5590
}
56-
useless[ErrorSequence(overlaps.String())] = dirs
57-
}
5891

59-
return useless, nil
92+
}
93+
return uselessBlocks
6094
}

0 commit comments

Comments
 (0)