Skip to content

Commit 368636f

Browse files
committed
sstable: show filenum when metadata is corrupted
Fixes #3804.
1 parent f8e117d commit 368636f

File tree

11 files changed

+37
-23
lines changed

11 files changed

+37
-23
lines changed

sstable/format.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,14 +210,14 @@ const (
210210

211211
// ParseTableFormat parses the given magic bytes and version into its
212212
// corresponding internal TableFormat.
213-
func ParseTableFormat(magic []byte, version uint32) (TableFormat, error) {
213+
func ParseTableFormat(magic []byte, version uint32, fileNum base.DiskFileNum) (TableFormat, error) {
214214
switch string(magic) {
215215
case levelDBMagic:
216216
return TableFormatLevelDB, nil
217217
case rocksDBMagic:
218218
if version != rocksDBFormatVersion2 {
219219
return TableFormatUnspecified, base.CorruptionErrorf(
220-
"pebble/table: unsupported rocksdb format version %d", errors.Safe(version),
220+
"pebble/table: invalid table %s (unsupported rocksdb format version %d)", errors.Safe(fileNum), errors.Safe(version),
221221
)
222222
}
223223
return TableFormatRocksDBv2, nil
@@ -233,12 +233,12 @@ func ParseTableFormat(magic []byte, version uint32) (TableFormat, error) {
233233
return TableFormatPebblev4, nil
234234
default:
235235
return TableFormatUnspecified, base.CorruptionErrorf(
236-
"pebble/table: unsupported pebble format version %d", errors.Safe(version),
236+
"pebble/table: invalid table %s (unsupported pebble format version %d)", errors.Safe(fileNum), errors.Safe(version),
237237
)
238238
}
239239
default:
240240
return TableFormatUnspecified, base.CorruptionErrorf(
241-
"pebble/table: invalid table (bad magic number: 0x%x)", magic,
241+
"pebble/table: invalid table %s (bad magic number: 0x%x)", errors.Safe(fileNum), magic,
242242
)
243243
}
244244
}

sstable/format_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,25 +60,25 @@ func TestTableFormat_RoundTrip(t *testing.T) {
6060
name: "Invalid RocksDB version",
6161
magic: rocksDBMagic,
6262
version: 1,
63-
wantErr: "pebble/table: unsupported rocksdb format version 1",
63+
wantErr: "pebble/table: invalid table 000001 (unsupported rocksdb format version 1)",
6464
},
6565
{
6666
name: "Invalid PebbleDB version",
6767
magic: pebbleDBMagic,
6868
version: 5,
69-
wantErr: "pebble/table: unsupported pebble format version 5",
69+
wantErr: "pebble/table: invalid table 000001 (unsupported pebble format version 5)",
7070
},
7171
{
7272
name: "Unknown magic string",
7373
magic: "foo",
74-
wantErr: "pebble/table: invalid table (bad magic number: 0x666f6f)",
74+
wantErr: "pebble/table: invalid table 000001 (bad magic number: 0x666f6f)",
7575
},
7676
}
7777

7878
for _, tc := range tcs {
7979
t.Run(tc.name, func(t *testing.T) {
8080
// Tuple -> TableFormat.
81-
f, err := ParseTableFormat([]byte(tc.magic), tc.version)
81+
f, err := ParseTableFormat([]byte(tc.magic), tc.version, 1)
8282
if tc.wantErr != "" {
8383
require.Error(t, err)
8484
require.Equal(t, tc.wantErr, err.Error())

sstable/reader.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,7 @@ func NewReader(ctx context.Context, f objstorage.Readable, o ReaderOptions) (*Re
979979
r.readable, objstorage.ReadBeforeForNewReader, &preallocRH)
980980
defer rh.Close()
981981

982-
footer, err := readFooter(ctx, f, rh, r.logger)
982+
footer, err := readFooter(ctx, f, rh, r.logger, r.cacheOpts.FileNum)
983983
if err != nil {
984984
r.err = err
985985
return nil, r.Close()

sstable/table.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -307,11 +307,12 @@ func readFooter(
307307
f objstorage.Readable,
308308
readHandle objstorage.ReadHandle,
309309
logger base.LoggerAndTracer,
310+
fileNum base.DiskFileNum,
310311
) (footer, error) {
311312
var footer footer
312313
size := f.Size()
313314
if size < minFooterLen {
314-
return footer, base.CorruptionErrorf("pebble/table: invalid table (file size is too small)")
315+
return footer, base.CorruptionErrorf("pebble/table: invalid table %s (file size is too small)", errors.Safe(fileNum))
315316
}
316317

317318
buf := make([]byte, maxFooterLen)
@@ -342,7 +343,7 @@ func readFooter(
342343
case levelDBMagic:
343344
if len(buf) < levelDBFooterLen {
344345
return footer, base.CorruptionErrorf(
345-
"pebble/table: invalid table (footer too short): %d", errors.Safe(len(buf)))
346+
"pebble/table: invalid table %s (footer too short): %d", errors.Safe(fileNum), errors.Safe(len(buf)))
346347
}
347348
footer.footerBH.Offset = uint64(off+int64(len(buf))) - levelDBFooterLen
348349
buf = buf[len(buf)-levelDBFooterLen:]
@@ -354,14 +355,14 @@ func readFooter(
354355
// NOTE: The Pebble magic string implies the same footer format as that used
355356
// by the RocksDBv2 table format.
356357
if len(buf) < rocksDBFooterLen {
357-
return footer, base.CorruptionErrorf("pebble/table: invalid table (footer too short): %d", errors.Safe(len(buf)))
358+
return footer, base.CorruptionErrorf("pebble/table: invalid table %s (footer too short): %d", errors.Safe(fileNum), errors.Safe(len(buf)))
358359
}
359360
footer.footerBH.Offset = uint64(off+int64(len(buf))) - rocksDBFooterLen
360361
buf = buf[len(buf)-rocksDBFooterLen:]
361362
footer.footerBH.Length = uint64(len(buf))
362363
version := binary.LittleEndian.Uint32(buf[rocksDBVersionOffset:rocksDBMagicOffset])
363364

364-
format, err := ParseTableFormat(magic, version)
365+
format, err := ParseTableFormat(magic, version, fileNum)
365366
if err != nil {
366367
return footer, err
367368
}
@@ -373,26 +374,26 @@ func readFooter(
373374
case block.ChecksumTypeXXHash64:
374375
footer.checksum = block.ChecksumTypeXXHash64
375376
default:
376-
return footer, base.CorruptionErrorf("pebble/table: unsupported checksum type %d", errors.Safe(footer.checksum))
377+
return footer, base.CorruptionErrorf("pebble/table: invalid table %s (unsupported checksum type %d)", errors.Safe(fileNum), errors.Safe(footer.checksum))
377378
}
378379
buf = buf[1:]
379380

380381
default:
381-
return footer, base.CorruptionErrorf("pebble/table: invalid table (bad magic number: 0x%x)", magic)
382+
return footer, base.CorruptionErrorf("pebble/table: invalid table %s (bad magic number: 0x%x)", errors.Safe(fileNum), magic)
382383
}
383384

384385
{
385386
end := uint64(size)
386387
var n int
387388
footer.metaindexBH, n = decodeBlockHandle(buf)
388389
if n == 0 || footer.metaindexBH.Offset+footer.metaindexBH.Length > end {
389-
return footer, base.CorruptionErrorf("pebble/table: invalid table (bad metaindex block handle)")
390+
return footer, base.CorruptionErrorf("pebble/table: invalid table %s (bad metaindex block handle)", errors.Safe(fileNum))
390391
}
391392
buf = buf[n:]
392393

393394
footer.indexBH, n = decodeBlockHandle(buf)
394395
if n == 0 || footer.indexBH.Offset+footer.indexBH.Length > end {
395-
return footer, base.CorruptionErrorf("pebble/table: invalid table (bad index block handle)")
396+
return footer, base.CorruptionErrorf("pebble/table: invalid table %s (bad index block handle)", errors.Safe(fileNum))
396397
}
397398
}
398399

sstable/table_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ func TestFooterRoundTrip(t *testing.T) {
588588
readable, err := NewSimpleReadable(f)
589589
require.NoError(t, err)
590590

591-
result, err := readFooter(context.Background(), readable, nil, base.NoopLoggerAndTracer{})
591+
result, err := readFooter(context.Background(), readable, nil, base.NoopLoggerAndTracer{}, 1)
592592
require.NoError(t, err)
593593
require.NoError(t, readable.Close())
594594

@@ -641,10 +641,12 @@ func TestReadFooter(t *testing.T) {
641641
readable, err := NewSimpleReadable(f)
642642
require.NoError(t, err)
643643

644-
if _, err := readFooter(context.Background(), readable, nil, base.NoopLoggerAndTracer{}); err == nil {
644+
if _, err := readFooter(context.Background(), readable, nil, base.NoopLoggerAndTracer{}, 1); err == nil {
645645
t.Fatalf("expected %q, but found success", c.expected)
646646
} else if !strings.Contains(err.Error(), c.expected) {
647647
t.Fatalf("expected %q, but found %v", c.expected, err)
648+
} else if !strings.Contains(err.Error(), "table 000001") {
649+
t.Fatalf("expected error to contain table number: %q", err)
648650
}
649651
})
650652
}

table_cache_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1025,7 +1025,7 @@ func TestTableCacheErrorBadMagicNumber(t *testing.T) {
10251025
t.Fatalf("expected failure, but found success")
10261026
}
10271027
require.Equal(t,
1028-
"pebble: backing file 000003 error: pebble/table: invalid table (bad magic number: 0xf09faab3f09faa00)",
1028+
"pebble: backing file 000003 error: pebble/table: invalid table 000003 (bad magic number: 0xf09faab3f09faa00)",
10291029
err.Error())
10301030
}
10311031

tool/db.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/cockroachdb/pebble/internal/base"
2020
"github.com/cockroachdb/pebble/internal/humanize"
2121
"github.com/cockroachdb/pebble/internal/manifest"
22+
"github.com/cockroachdb/pebble/internal/sstableinternal"
2223
"github.com/cockroachdb/pebble/objstorage"
2324
"github.com/cockroachdb/pebble/objstorage/objstorageprovider"
2425
"github.com/cockroachdb/pebble/record"
@@ -883,6 +884,15 @@ func (d *dbT) addProps(
883884
if err != nil {
884885
return err
885886
}
887+
opts := sstable.ReaderOptions{
888+
Mergers: d.mergers,
889+
Comparers: d.comparers,
890+
}
891+
opts.SetInternal(sstableinternal.ReaderOptions{
892+
CacheOpts: sstableinternal.CacheOptions{
893+
FileNum: m.FileBacking.DiskFileNum,
894+
},
895+
})
886896
r, err := sstable.NewReader(ctx, f, sstable.ReaderOptions{
887897
Mergers: d.mergers,
888898
Comparers: d.comparers,

tool/find.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,8 @@ func (f *findT) searchTables(stdout io.Writer, searchKey []byte, refs []findRef)
446446
}
447447
opts.SetInternal(sstableinternal.ReaderOptions{
448448
CacheOpts: sstableinternal.CacheOptions{
449-
Cache: cache,
449+
Cache: cache,
450+
FileNum: fl.DiskFileNum,
450451
},
451452
})
452453
readable, err := sstable.NewSimpleReadable(tf)

tool/testdata/find

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,4 +137,4 @@ hex:636363
137137
----
138138
000002.sst
139139
test formatter: ccc#14,MERGE
140-
Unable to decode sstable find-mixed/000001.sst, pebble/table: invalid table (file size is too small)
140+
Unable to decode sstable find-mixed/000001.sst, pebble/table: invalid table 000001 (file size is too small)

tool/testdata/sstable_check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ sstable check
5151
testdata/bad-magic.sst
5252
----
5353
bad-magic.sst
54-
pebble/table: invalid table (bad magic number: 0xf6cff485b741e288)
54+
pebble/table: invalid table 000000 (bad magic number: 0xf6cff485b741e288)
5555

5656
sstable check
5757
./testdata/mixed/000005.sst

0 commit comments

Comments
 (0)