Skip to content

Commit

Permalink
Merge pull request #425 from ahrtr/move_inode_operation_into_common_2…
Browse files Browse the repository at this point in the history
…0230315

move inode operations(read/write) into package internal/common
  • Loading branch information
ahrtr authored Mar 15, 2023
2 parents e06ca03 + 15d561e commit 87a1781
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 48 deletions.
60 changes: 60 additions & 0 deletions internal/common/inode.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package common

import "unsafe"

// Inode represents an internal node inside of a node.
// It can be used to point to elements in a page or point
// to an element which hasn't been added to a page yet.
Expand Down Expand Up @@ -43,3 +45,61 @@ func (in *Inode) Value() []byte {
func (in *Inode) SetValue(value []byte) {
in.value = value
}

func ReadInodeFromPage(p *Page) Inodes {
inodes := make(Inodes, int(p.Count()))
isLeaf := p.IsLeafPage()
for i := 0; i < int(p.Count()); i++ {
inode := &inodes[i]
if isLeaf {
elem := p.LeafPageElement(uint16(i))
inode.SetFlags(elem.Flags())
inode.SetKey(elem.Key())
inode.SetValue(elem.Value())
} else {
elem := p.BranchPageElement(uint16(i))
inode.SetPgid(elem.Pgid())
inode.SetKey(elem.Key())
}
Assert(len(inode.Key()) > 0, "read: zero-length inode key")
}

return inodes
}

func WriteInodeToPage(inodes Inodes, p *Page) uint32 {
// Loop over each item and write it to the page.
// off tracks the offset into p of the start of the next data.
off := unsafe.Sizeof(*p) + p.PageElementSize()*uintptr(len(inodes))
isLeaf := p.IsLeafPage()
for i, item := range inodes {
Assert(len(item.Key()) > 0, "write: zero-length inode key")

// Create a slice to write into of needed size and advance
// byte pointer for next iteration.
sz := len(item.Key()) + len(item.Value())
b := UnsafeByteSlice(unsafe.Pointer(p), off, 0, sz)
off += uintptr(sz)

// Write the page element.
if isLeaf {
elem := p.LeafPageElement(uint16(i))
elem.SetPos(uint32(uintptr(unsafe.Pointer(&b[0])) - uintptr(unsafe.Pointer(elem))))
elem.SetFlags(item.Flags())
elem.SetKsize(uint32(len(item.Key())))
elem.SetVsize(uint32(len(item.Value())))
} else {
elem := p.BranchPageElement(uint16(i))
elem.SetPos(uint32(uintptr(unsafe.Pointer(&b[0])) - uintptr(unsafe.Pointer(elem))))
elem.SetKsize(uint32(len(item.Key())))
elem.SetPgid(item.Pgid())
Assert(elem.Pgid() != p.Id(), "write: circular dependency occurred")
}

// Write data for the element to the end of the page.
l := copy(b, item.Key())
copy(b[l:], item.Value())
}

return uint32(off)
}
7 changes: 7 additions & 0 deletions internal/common/page.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,13 @@ func (p *Page) hexdump(n int) {
fmt.Fprintf(os.Stderr, "%x\n", buf)
}

func (p *Page) PageElementSize() uintptr {
if p.IsLeafPage() {
return LeafPageElementSize
}
return BranchPageElementSize
}

func (p *Page) Id() Pgid {
return p.id
}
Expand Down
50 changes: 2 additions & 48 deletions node.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bytes"
"fmt"
"sort"
"unsafe"

"go.etcd.io/bbolt/internal/common"
)
Expand Down Expand Up @@ -163,22 +162,7 @@ func (n *node) del(key []byte) {
func (n *node) read(p *common.Page) {
n.pgid = p.Id()
n.isLeaf = p.IsLeafPage()
n.inodes = make(common.Inodes, int(p.Count()))

for i := 0; i < int(p.Count()); i++ {
inode := &n.inodes[i]
if n.isLeaf {
elem := p.LeafPageElement(uint16(i))
inode.SetFlags(elem.Flags())
inode.SetKey(elem.Key())
inode.SetValue(elem.Value())
} else {
elem := p.BranchPageElement(uint16(i))
inode.SetPgid(elem.Pgid())
inode.SetKey(elem.Key())
}
common.Assert(len(inode.Key()) > 0, "read: zero-length inode key")
}
n.inodes = common.ReadInodeFromPage(p)

// Save first key, so we can find the node in the parent when we spill.
if len(n.inodes) > 0 {
Expand Down Expand Up @@ -212,37 +196,7 @@ func (n *node) write(p *common.Page) {
return
}

// Loop over each item and write it to the page.
// off tracks the offset into p of the start of the next data.
off := unsafe.Sizeof(*p) + n.pageElementSize()*uintptr(len(n.inodes))
for i, item := range n.inodes {
common.Assert(len(item.Key()) > 0, "write: zero-length inode key")

// Create a slice to write into of needed size and advance
// byte pointer for next iteration.
sz := len(item.Key()) + len(item.Value())
b := common.UnsafeByteSlice(unsafe.Pointer(p), off, 0, sz)
off += uintptr(sz)

// Write the page element.
if n.isLeaf {
elem := p.LeafPageElement(uint16(i))
elem.SetPos(uint32(uintptr(unsafe.Pointer(&b[0])) - uintptr(unsafe.Pointer(elem))))
elem.SetFlags(item.Flags())
elem.SetKsize(uint32(len(item.Key())))
elem.SetVsize(uint32(len(item.Value())))
} else {
elem := p.BranchPageElement(uint16(i))
elem.SetPos(uint32(uintptr(unsafe.Pointer(&b[0])) - uintptr(unsafe.Pointer(elem))))
elem.SetKsize(uint32(len(item.Key())))
elem.SetPgid(item.Pgid())
common.Assert(elem.Pgid() != p.Id(), "write: circular dependency occurred")
}

// Write data for the element to the end of the page.
l := copy(b, item.Key())
copy(b[l:], item.Value())
}
common.WriteInodeToPage(n.inodes, p)

// DEBUG ONLY: n.dump()
}
Expand Down

0 comments on commit 87a1781

Please sign in to comment.