From a3a9877de629e1e63f60b26f0d8f094355b3e122 Mon Sep 17 00:00:00 2001 From: Benjamin Wang Date: Wed, 8 Mar 2023 10:46:18 +0800 Subject: [PATCH] encapsulate the logic of checking the page type Signed-off-by: Benjamin Wang --- bucket.go | 6 +++--- cursor.go | 4 ++-- freelist.go | 4 ++-- internal/common/page.go | 24 ++++++++++++++++++++---- node.go | 2 +- tx.go | 2 +- tx_check.go | 6 +++--- 7 files changed, 32 insertions(+), 16 deletions(-) diff --git a/bucket.go b/bucket.go index b5a796deb..52f9790ec 100644 --- a/bucket.go +++ b/bucket.go @@ -410,7 +410,7 @@ func (b *Bucket) Stats() BucketStats { s.InlineBucketN += 1 } b.forEachPage(func(p *common.Page, depth int, pgstack []common.Pgid) { - if (p.Flags() & common.LeafPageFlag) != 0 { + if p.IsLeafPage() { s.KeyN += int(p.Count()) // used totals the used bytes for the page @@ -450,7 +450,7 @@ func (b *Bucket) Stats() BucketStats { } } } - } else if (p.Flags() & common.BranchPageFlag) != 0 { + } else if p.IsBranchPage() { s.BranchPageN++ lastElement := p.BranchPageElement(p.Count() - 1) @@ -514,7 +514,7 @@ func (b *Bucket) _forEachPageNode(pgId common.Pgid, depth int, fn func(*common.P // Recursively loop over children. if p != nil { - if (p.Flags() & common.BranchPageFlag) != 0 { + if p.IsBranchPage() { for i := 0; i < int(p.Count()); i++ { elem := p.BranchPageElement(uint16(i)) b._forEachPageNode(elem.Pgid(), depth+1, fn) diff --git a/cursor.go b/cursor.go index 209c960dc..14556e508 100644 --- a/cursor.go +++ b/cursor.go @@ -272,7 +272,7 @@ func (c *Cursor) prev() (key []byte, value []byte, flags uint32) { // search recursively performs a binary search against a given page/node until it finds a given key. func (c *Cursor) search(key []byte, pgId common.Pgid) { p, n := c.bucket.pageNode(pgId) - if p != nil && (p.Flags()&(common.BranchPageFlag|common.LeafPageFlag)) == 0 { + if p != nil && !p.IsBranchPage() && !p.IsLeafPage() { panic(fmt.Sprintf("invalid page type: %d: %x", p.Id(), p.Flags())) } e := elemRef{page: p, node: n} @@ -410,7 +410,7 @@ func (r *elemRef) isLeaf() bool { if r.node != nil { return r.node.isLeaf } - return (r.page.Flags() & common.LeafPageFlag) != 0 + return r.page.IsLeafPage() } // count returns the number of inodes or page elements. diff --git a/freelist.go b/freelist.go index dfccc503b..24dfc3e48 100644 --- a/freelist.go +++ b/freelist.go @@ -166,7 +166,7 @@ func (f *freelist) free(txid common.Txid, p *common.Page) { allocTxid, ok := f.allocs[p.Id()] if ok { delete(f.allocs, p.Id()) - } else if (p.Flags() & common.FreelistPageFlag) != 0 { + } else if p.IsFreelistPage() { // Freelist is always allocated by prior tx. allocTxid = txid - 1 } @@ -265,7 +265,7 @@ func (f *freelist) freed(pgId common.Pgid) bool { // read initializes the freelist from a freelist page. func (f *freelist) read(p *common.Page) { - if (p.Flags() & common.FreelistPageFlag) == 0 { + if !p.IsFreelistPage() { panic(fmt.Sprintf("invalid freelist page: %d, page type is %s", p.Id(), p.Typ())) } diff --git a/internal/common/page.go b/internal/common/page.go index 0975f738d..cd8abf831 100644 --- a/internal/common/page.go +++ b/internal/common/page.go @@ -45,18 +45,34 @@ func NewPage(id Pgid, flags, count uint16, overflow uint32) *Page { // Typ returns a human-readable page type string used for debugging. func (p *Page) Typ() string { - if (p.flags & BranchPageFlag) != 0 { + if p.IsBranchPage() { return "branch" - } else if (p.flags & LeafPageFlag) != 0 { + } else if p.IsLeafPage() { return "leaf" - } else if (p.flags & MetaPageFlag) != 0 { + } else if p.IsMetaPage() { return "meta" - } else if (p.flags & FreelistPageFlag) != 0 { + } else if p.IsFreelistPage() { return "freelist" } return fmt.Sprintf("unknown<%02x>", p.flags) } +func (p *Page) IsBranchPage() bool { + return p.flags&BranchPageFlag != 0 +} + +func (p *Page) IsLeafPage() bool { + return p.flags&LeafPageFlag != 0 +} + +func (p *Page) IsMetaPage() bool { + return p.flags&MetaPageFlag != 0 +} + +func (p *Page) IsFreelistPage() bool { + return p.flags&FreelistPageFlag != 0 +} + // Meta returns a pointer to the metadata section of the page. func (p *Page) Meta() *Meta { return (*Meta)(UnsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p))) diff --git a/node.go b/node.go index b97028d53..5f3518faf 100644 --- a/node.go +++ b/node.go @@ -162,7 +162,7 @@ func (n *node) del(key []byte) { // read initializes the node from a page. func (n *node) read(p *common.Page) { n.pgid = p.Id() - n.isLeaf = (p.Flags() & common.LeafPageFlag) != 0 + n.isLeaf = p.IsLeafPage() n.inodes = make(common.Inodes, int(p.Count())) for i := 0; i < int(p.Count()); i++ { diff --git a/tx.go b/tx.go index 343644235..67362b66d 100644 --- a/tx.go +++ b/tx.go @@ -548,7 +548,7 @@ func (tx *Tx) forEachPageInternal(pgidstack []common.Pgid, fn func(*common.Page, fn(p, len(pgidstack)-1, pgidstack) // Recursively loop over children. - if (p.Flags() & common.BranchPageFlag) != 0 { + if p.IsBranchPage() { for i := 0; i < int(p.Count()); i++ { elem := p.BranchPageElement(uint16(i)) tx.forEachPageInternal(append(pgidstack, elem.Pgid()), fn) diff --git a/tx_check.go b/tx_check.go index 2ee03ec62..ee72cda22 100644 --- a/tx_check.go +++ b/tx_check.go @@ -99,7 +99,7 @@ func (tx *Tx) checkBucket(b *Bucket, reachable map[common.Pgid]*common.Page, fre // We should only encounter un-freed leaf and branch pages. if freed[p.Id()] { ch <- fmt.Errorf("page %d: reachable freed", int(p.Id())) - } else if (p.Flags()&common.BranchPageFlag) == 0 && (p.Flags()&common.LeafPageFlag) == 0 { + } else if !p.IsBranchPage() && !p.IsLeafPage() { ch <- fmt.Errorf("page %d: invalid type: %s (stack: %v)", int(p.Id()), p.Typ(), stack) } }) @@ -135,7 +135,7 @@ func (tx *Tx) recursivelyCheckPagesInternal( p := tx.page(pgId) pagesStack = append(pagesStack, pgId) switch { - case p.Flags()&common.BranchPageFlag != 0: + case p.IsBranchPage(): // For branch page we navigate ranges of all subpages. runningMin := minKeyClosed for i := range p.BranchPageElements() { @@ -150,7 +150,7 @@ func (tx *Tx) recursivelyCheckPagesInternal( runningMin = maxKeyInSubtree } return maxKeyInSubtree - case p.Flags()&common.LeafPageFlag != 0: + case p.IsLeafPage(): runningMin := minKeyClosed for i := range p.LeafPageElements() { elem := p.LeafPageElement(uint16(i))