104 lines
2.4 KiB
Go
104 lines
2.4 KiB
Go
package tsm1
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"hash/crc32"
|
|
"io"
|
|
"os"
|
|
|
|
"github.com/influxdata/influxdb"
|
|
"github.com/influxdata/influxdb/tsdb"
|
|
"github.com/influxdata/influxdb/tsdb/cursors"
|
|
)
|
|
|
|
type VerifyTSM struct {
|
|
Stdout io.Writer
|
|
Paths []string
|
|
OrgID influxdb.ID
|
|
BucketID influxdb.ID
|
|
}
|
|
|
|
func (v *VerifyTSM) Run() error {
|
|
for _, path := range v.Paths {
|
|
if err := v.processFile(path); err != nil {
|
|
fmt.Fprintf(v.Stdout, "Error processing file %q: %v", path, err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (v *VerifyTSM) processFile(path string) error {
|
|
fmt.Println("processing file: " + path)
|
|
|
|
file, err := os.OpenFile(path, os.O_RDONLY, 0600)
|
|
if err != nil {
|
|
return fmt.Errorf("OpenFile: %v", err)
|
|
}
|
|
|
|
reader, err := NewTSMReader(file)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create TSM reader for %q: %v", path, err)
|
|
}
|
|
defer reader.Close()
|
|
|
|
var start []byte
|
|
if v.OrgID.Valid() {
|
|
if v.BucketID.Valid() {
|
|
v := tsdb.EncodeName(v.OrgID, v.BucketID)
|
|
start = v[:]
|
|
} else {
|
|
v := tsdb.EncodeOrgName(v.OrgID)
|
|
start = v[:]
|
|
}
|
|
}
|
|
|
|
var ts cursors.TimestampArray
|
|
count := 0
|
|
totalErrors := 0
|
|
iter := reader.Iterator(start)
|
|
for iter.Next() {
|
|
key := iter.Key()
|
|
if len(start) > 0 && (len(key) < len(start) || !bytes.Equal(key[:len(start)], start)) {
|
|
break
|
|
}
|
|
|
|
entries := iter.Entries()
|
|
for i := range entries {
|
|
entry := &entries[i]
|
|
|
|
checksum, buf, err := reader.ReadBytes(entry, nil)
|
|
if err != nil {
|
|
fmt.Fprintf(v.Stdout, "could not read block %d due to error: %q\n", count, err)
|
|
count++
|
|
continue
|
|
}
|
|
|
|
if expected := crc32.ChecksumIEEE(buf); checksum != expected {
|
|
totalErrors++
|
|
fmt.Fprintf(v.Stdout, "unexpected checksum %d, expected %d for key %v, block %d\n", checksum, expected, key, count)
|
|
}
|
|
|
|
if err = DecodeTimestampArrayBlock(buf, &ts); err != nil {
|
|
totalErrors++
|
|
fmt.Fprintf(v.Stdout, "unable to decode timestamps for block %d: %q\n", count, err)
|
|
}
|
|
|
|
if got, exp := entry.MinTime, ts.MinTime(); got != exp {
|
|
totalErrors++
|
|
fmt.Fprintf(v.Stdout, "unexpected min time %d, expected %d for block %d: %q\n", got, exp, count, err)
|
|
}
|
|
if got, exp := entry.MaxTime, ts.MaxTime(); got != exp {
|
|
totalErrors++
|
|
fmt.Fprintf(v.Stdout, "unexpected max time %d, expected %d for block %d: %q\n", got, exp, count, err)
|
|
}
|
|
|
|
count++
|
|
}
|
|
}
|
|
|
|
fmt.Fprintf(v.Stdout, "Completed checking %d block(s)\n", count)
|
|
|
|
return nil
|
|
}
|