Skip to content

Commit 6907b5f

Browse files
committed
manifest: validate BlobReferences and BlobFileSet agree
Sometimes in invariants builds, validate that the set of unique BlobFileIDs contained in TableMetadata BlobReferences is exactly the set of BlobFileIDs in the Version's BlobFileSet.
1 parent 300a478 commit 6907b5f

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

internal/manifest/blob_metadata.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package manifest
77
import (
88
stdcmp "cmp"
99
"fmt"
10+
"iter"
1011
"slices"
1112
"sync/atomic"
1213

@@ -330,6 +331,11 @@ func MakeBlobFileSet(entries []BlobFileMetadata) BlobFileSet {
330331
return BlobFileSet{tree: makeBTree(btreeCmpBlobFileID, entries)}
331332
}
332333

334+
// All returns an iterator over all the blob files in the set.
335+
func (s *BlobFileSet) All() iter.Seq[BlobFileMetadata] {
336+
return s.tree.All()
337+
}
338+
333339
// clone returns a copy-on-write clone of the blob file set.
334340
func (s *BlobFileSet) clone() BlobFileSet {
335341
return BlobFileSet{tree: s.tree.Clone()}

internal/manifest/version.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"bytes"
99
"fmt"
1010
"iter"
11+
"maps"
1112
"slices"
1213
"sort"
1314
"strings"
@@ -600,6 +601,46 @@ func (v *Version) CheckOrdering() error {
600601
return nil
601602
}
602603

604+
// validateBlobFileInvariants validates invariants around blob files. Currently
605+
// it validates that the set of BlobFileIDs referenced by the Version's tables'
606+
// blob references is exactly the same as the set of BlobFileIDs present in the
607+
// Version's blob files B-Tree.
608+
func (v *Version) validateBlobFileInvariants() error {
609+
// Collect all the blob file IDs that are referenced by the Version's
610+
// tables' blob references.
611+
var referencedFileIDs []base.BlobFileID
612+
{
613+
referencedFileIDsMap := make(map[base.BlobFileID]struct{}, v.BlobFiles.tree.Count())
614+
for i := 0; i < len(v.Levels); i++ {
615+
for table := range v.Levels[i].All() {
616+
for _, br := range table.BlobReferences {
617+
referencedFileIDsMap[br.FileID] = struct{}{}
618+
}
619+
}
620+
}
621+
referencedFileIDs = slices.Collect(maps.Keys(referencedFileIDsMap))
622+
slices.Sort(referencedFileIDs)
623+
}
624+
625+
// Collect all the blob file IDs that are present in the Version's blob
626+
// files B-Tree.
627+
var versionBlobFileIDs []base.BlobFileID
628+
{
629+
versionBlobFileIDsMap := make(map[base.BlobFileID]struct{}, v.BlobFiles.tree.Count())
630+
for bf := range v.BlobFiles.All() {
631+
versionBlobFileIDsMap[bf.FileID] = struct{}{}
632+
}
633+
versionBlobFileIDs = slices.Collect(maps.Keys(versionBlobFileIDsMap))
634+
slices.Sort(versionBlobFileIDs)
635+
}
636+
637+
if !slices.Equal(referencedFileIDs, versionBlobFileIDs) {
638+
return base.AssertionFailedf("divergence between referenced BlobFileIDs and Version's BlobFiles B-Tree: %v vs %v",
639+
referencedFileIDs, versionBlobFileIDs)
640+
}
641+
return nil
642+
}
643+
603644
// VersionList holds a list of versions. The versions are ordered from oldest
604645
// to newest.
605646
type VersionList struct {

internal/manifest/version_edit.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818

1919
"github.com/cockroachdb/errors"
2020
"github.com/cockroachdb/pebble/internal/base"
21+
"github.com/cockroachdb/pebble/internal/invariants"
2122
"github.com/cockroachdb/pebble/internal/strparse"
2223
"github.com/cockroachdb/pebble/sstable"
2324
)
@@ -1296,5 +1297,14 @@ func (b *BulkVersionEdit) Apply(curr *Version, readCompactionRate int64) (*Versi
12961297
}
12971298
}
12981299
}
1300+
1301+
// In invariants builds, sometimes check invariants across all blob files
1302+
// and their references.
1303+
if invariants.Sometimes(20) {
1304+
if err := v.validateBlobFileInvariants(); err != nil {
1305+
return nil, err
1306+
}
1307+
}
1308+
12991309
return v, nil
13001310
}

0 commit comments

Comments
 (0)