Skip to content

Commit de6c42b

Browse files
authored
Merge pull request #651 from ahrtr/renaming_20231227
Refactor the implementation of check
2 parents 47cc272 + 23c97d5 commit de6c42b

File tree

2 files changed

+34
-30
lines changed

2 files changed

+34
-30
lines changed

db.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1206,7 +1206,7 @@ func (db *DB) freepages() []common.Pgid {
12061206
panic(fmt.Sprintf("freepages: failed to get all reachable pages (%v)", e))
12071207
}
12081208
}()
1209-
tx.checkBucket(&tx.root, reachable, nofreed, HexKVStringer(), ech)
1209+
tx.recursivelyCheckBucket(&tx.root, reachable, nofreed, HexKVStringer(), ech)
12101210
close(ech)
12111211

12121212
// TODO: If check bucket reported any corruptions (ech) we shouldn't proceed to freeing the pages.

tx_check.go

+33-29
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ func (tx *Tx) check(kvStringer KVStringer, ch chan error) {
5757
}
5858

5959
// Recursively check buckets.
60-
tx.checkBucket(&tx.root, reachable, freed, kvStringer, ch)
60+
tx.recursivelyCheckBucket(&tx.root, reachable, freed, kvStringer, ch)
6161

6262
// Ensure all pages below high water mark are either reachable or freed.
6363
for i := common.Pgid(0); i < tx.meta.Pgid(); i++ {
@@ -71,7 +71,7 @@ func (tx *Tx) check(kvStringer KVStringer, ch chan error) {
7171
close(ch)
7272
}
7373

74-
func (tx *Tx) checkBucket(b *Bucket, reachable map[common.Pgid]*common.Page, freed map[common.Pgid]bool,
74+
func (tx *Tx) recursivelyCheckBucket(b *Bucket, reachable map[common.Pgid]*common.Page, freed map[common.Pgid]bool,
7575
kvStringer KVStringer, ch chan error) {
7676
// Ignore inline buckets.
7777
if b.RootPage() == 0 {
@@ -80,52 +80,56 @@ func (tx *Tx) checkBucket(b *Bucket, reachable map[common.Pgid]*common.Page, fre
8080

8181
// Check every page used by this bucket.
8282
b.tx.forEachPage(b.RootPage(), func(p *common.Page, _ int, stack []common.Pgid) {
83-
if p.Id() > tx.meta.Pgid() {
84-
ch <- fmt.Errorf("page %d: out of bounds: %d (stack: %v)", int(p.Id()), int(b.tx.meta.Pgid()), stack)
85-
}
86-
87-
// Ensure each page is only referenced once.
88-
for i := common.Pgid(0); i <= common.Pgid(p.Overflow()); i++ {
89-
var id = p.Id() + i
90-
if _, ok := reachable[id]; ok {
91-
ch <- fmt.Errorf("page %d: multiple references (stack: %v)", int(id), stack)
92-
}
93-
reachable[id] = p
94-
}
95-
96-
// We should only encounter un-freed leaf and branch pages.
97-
if freed[p.Id()] {
98-
ch <- fmt.Errorf("page %d: reachable freed", int(p.Id()))
99-
} else if !p.IsBranchPage() && !p.IsLeafPage() {
100-
ch <- fmt.Errorf("page %d: invalid type: %s (stack: %v)", int(p.Id()), p.Typ(), stack)
101-
}
83+
verifyPageReachable(p, tx.meta.Pgid(), stack, reachable, freed, ch)
10284
})
10385

104-
tx.recursivelyCheckPages(b.RootPage(), kvStringer.KeyToString, ch)
86+
tx.recursivelyCheckPageKeyOrder(b.RootPage(), kvStringer.KeyToString, ch)
10587

10688
// Check each bucket within this bucket.
10789
_ = b.ForEachBucket(func(k []byte) error {
10890
if child := b.Bucket(k); child != nil {
109-
tx.checkBucket(child, reachable, freed, kvStringer, ch)
91+
tx.recursivelyCheckBucket(child, reachable, freed, kvStringer, ch)
11092
}
11193
return nil
11294
})
11395
}
11496

115-
// recursivelyCheckPages confirms database consistency with respect to b-tree
97+
func verifyPageReachable(p *common.Page, hwm common.Pgid, stack []common.Pgid, reachable map[common.Pgid]*common.Page, freed map[common.Pgid]bool, ch chan error) {
98+
if p.Id() > hwm {
99+
ch <- fmt.Errorf("page %d: out of bounds: %d (stack: %v)", int(p.Id()), int(hwm), stack)
100+
}
101+
102+
// Ensure each page is only referenced once.
103+
for i := common.Pgid(0); i <= common.Pgid(p.Overflow()); i++ {
104+
var id = p.Id() + i
105+
if _, ok := reachable[id]; ok {
106+
ch <- fmt.Errorf("page %d: multiple references (stack: %v)", int(id), stack)
107+
}
108+
reachable[id] = p
109+
}
110+
111+
// We should only encounter un-freed leaf and branch pages.
112+
if freed[p.Id()] {
113+
ch <- fmt.Errorf("page %d: reachable freed", int(p.Id()))
114+
} else if !p.IsBranchPage() && !p.IsLeafPage() {
115+
ch <- fmt.Errorf("page %d: invalid type: %s (stack: %v)", int(p.Id()), p.Typ(), stack)
116+
}
117+
}
118+
119+
// recursivelyCheckPageKeyOrder verifies database consistency with respect to b-tree
116120
// key order constraints:
117121
// - keys on pages must be sorted
118122
// - keys on children pages are between 2 consecutive keys on the parent's branch page).
119-
func (tx *Tx) recursivelyCheckPages(pgId common.Pgid, keyToString func([]byte) string, ch chan error) {
120-
tx.recursivelyCheckPagesInternal(pgId, nil, nil, nil, keyToString, ch)
123+
func (tx *Tx) recursivelyCheckPageKeyOrder(pgId common.Pgid, keyToString func([]byte) string, ch chan error) {
124+
tx.recursivelyCheckPageKeyOrderInternal(pgId, nil, nil, nil, keyToString, ch)
121125
}
122126

123-
// recursivelyCheckPagesInternal verifies that all keys in the subtree rooted at `pgid` are:
127+
// recursivelyCheckPageKeyOrderInternal verifies that all keys in the subtree rooted at `pgid` are:
124128
// - >=`minKeyClosed` (can be nil)
125129
// - <`maxKeyOpen` (can be nil)
126130
// - Are in right ordering relationship to their parents.
127131
// `pagesStack` is expected to contain IDs of pages from the tree root to `pgid` for the clean debugging message.
128-
func (tx *Tx) recursivelyCheckPagesInternal(
132+
func (tx *Tx) recursivelyCheckPageKeyOrderInternal(
129133
pgId common.Pgid, minKeyClosed, maxKeyOpen []byte, pagesStack []common.Pgid,
130134
keyToString func([]byte) string, ch chan error) (maxKeyInSubtree []byte) {
131135

@@ -143,7 +147,7 @@ func (tx *Tx) recursivelyCheckPagesInternal(
143147
if i < len(p.BranchPageElements())-1 {
144148
maxKey = p.BranchPageElement(uint16(i + 1)).Key()
145149
}
146-
maxKeyInSubtree = tx.recursivelyCheckPagesInternal(elem.Pgid(), elem.Key(), maxKey, pagesStack, keyToString, ch)
150+
maxKeyInSubtree = tx.recursivelyCheckPageKeyOrderInternal(elem.Pgid(), elem.Key(), maxKey, pagesStack, keyToString, ch)
147151
runningMin = maxKeyInSubtree
148152
}
149153
return maxKeyInSubtree

0 commit comments

Comments
 (0)