Skip to content

Commit 248e6f8

Browse files
ahrtrElbehery
authored andcommitted
enhance check functionality to support checking starting from a pageId
Signed-off-by: Benjamin Wang <benjamin.ahrtr@gmail.com>
1 parent 6383011 commit 248e6f8

File tree

1 file changed

+65
-9
lines changed

1 file changed

+65
-9
lines changed

tx_check.go

+65-9
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,63 @@ func (tx *Tx) check(cfg checkConfig, ch chan error) {
6060
}
6161
}
6262

63-
// Recursively check buckets.
64-
tx.recursivelyCheckBucket(&tx.root, reachable, freed, cfg.kvStringer, ch)
65-
66-
// Ensure all pages below high water mark are either reachable or freed.
67-
for i := common.Pgid(0); i < tx.meta.Pgid(); i++ {
68-
_, isReachable := reachable[i]
69-
if !isReachable && !freed[i] {
70-
ch <- fmt.Errorf("page %d: unreachable unfreed", int(i))
63+
if cfg.pageId == 0 {
64+
// Check the whole db file, starting from the root bucket and
65+
// recursively check all child buckets.
66+
tx.recursivelyCheckBucket(&tx.root, reachable, freed, cfg.kvStringer, ch)
67+
68+
// Ensure all pages below high water mark are either reachable or freed.
69+
for i := common.Pgid(0); i < tx.meta.Pgid(); i++ {
70+
_, isReachable := reachable[i]
71+
if !isReachable && !freed[i] {
72+
ch <- fmt.Errorf("page %d: unreachable unfreed", int(i))
73+
}
74+
}
75+
} else {
76+
// Check the db file starting from a specified pageId.
77+
if cfg.pageId < 2 || cfg.pageId >= uint(tx.meta.Pgid()) {
78+
ch <- fmt.Errorf("page ID (%d) out of range [%d, %d)", cfg.pageId, 2, tx.meta.Pgid())
79+
return
80+
}
81+
82+
tx.recursivelyCheckPage(common.Pgid(cfg.pageId), reachable, freed, cfg.kvStringer, ch)
83+
}
84+
}
85+
86+
func (tx *Tx) recursivelyCheckPage(pageId common.Pgid, reachable map[common.Pgid]*common.Page, freed map[common.Pgid]bool,
87+
kvStringer KVStringer, ch chan error) {
88+
tx.checkInvariantProperties(pageId, reachable, freed, kvStringer, ch)
89+
tx.recursivelyCheckBucketInPage(pageId, reachable, freed, kvStringer, ch)
90+
}
91+
92+
func (tx *Tx) recursivelyCheckBucketInPage(pageId common.Pgid, reachable map[common.Pgid]*common.Page, freed map[common.Pgid]bool,
93+
kvStringer KVStringer, ch chan error) {
94+
p := tx.page(pageId)
95+
96+
switch {
97+
case p.IsBranchPage():
98+
for i := range p.BranchPageElements() {
99+
elem := p.BranchPageElement(uint16(i))
100+
tx.recursivelyCheckBucketInPage(elem.Pgid(), reachable, freed, kvStringer, ch)
101+
}
102+
case p.IsLeafPage():
103+
for i := range p.LeafPageElements() {
104+
elem := p.LeafPageElement(uint16(i))
105+
if elem.Flags()&common.BucketLeafFlag != 0 {
106+
107+
inBkt := common.NewInBucket(pageId, 0)
108+
tmpBucket := Bucket{
109+
InBucket: &inBkt,
110+
rootNode: &node{isLeaf: p.IsLeafPage()},
111+
FillPercent: DefaultFillPercent,
112+
}
113+
if child := tmpBucket.Bucket(elem.Key()); child != nil {
114+
tx.recursivelyCheckBucket(&tmpBucket, reachable, freed, kvStringer, ch)
115+
}
116+
}
71117
}
118+
default:
119+
ch <- fmt.Errorf("unexpected page type (flags: %x) for pgId:%d", p.Flags(), pageId)
72120
}
73121
}
74122

@@ -167,7 +215,7 @@ func (tx *Tx) recursivelyCheckPageKeyOrderInternal(
167215
return p.LeafPageElement(p.Count() - 1).Key()
168216
}
169217
default:
170-
ch <- fmt.Errorf("unexpected page type for pgId:%d", pgId)
218+
ch <- fmt.Errorf("unexpected page type (flags: %x) for pgId:%d", p.Flags(), pgId)
171219
}
172220
return maxKeyInSubtree
173221
}
@@ -202,6 +250,7 @@ func verifyKeyOrder(pgId common.Pgid, pageType string, index int, key []byte, pr
202250

203251
type checkConfig struct {
204252
kvStringer KVStringer
253+
pageId uint
205254
}
206255

207256
type CheckOption func(options *checkConfig)
@@ -212,6 +261,13 @@ func WithKVStringer(kvStringer KVStringer) CheckOption {
212261
}
213262
}
214263

264+
// WithPageId sets a page ID from which the check command starts to check
265+
func WithPageId(pageId uint) CheckOption {
266+
return func(c *checkConfig) {
267+
c.pageId = pageId
268+
}
269+
}
270+
215271
// KVStringer allows to prepare human-readable diagnostic messages.
216272
type KVStringer interface {
217273
KeyToString([]byte) string

0 commit comments

Comments
 (0)