mirror of https://github.com/etcd-io/bbolt.git
refactor: move inode to internal/common package
Signed-off-by: Benjamin Wang <wachao@vmware.com>pull/407/head
parent
ea511567eb
commit
852b1df32f
|
@ -523,7 +523,7 @@ func (b *Bucket) _forEachPageNode(pgId common.Pgid, depth int, fn func(*common.P
|
||||||
} else {
|
} else {
|
||||||
if !n.isLeaf {
|
if !n.isLeaf {
|
||||||
for _, inode := range n.inodes {
|
for _, inode := range n.inodes {
|
||||||
b._forEachPageNode(inode.pgid, depth+1, fn)
|
b._forEachPageNode(inode.Pgid(), depth+1, fn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -602,9 +602,9 @@ func (b *Bucket) inlineable() bool {
|
||||||
// our threshold for inline bucket size.
|
// our threshold for inline bucket size.
|
||||||
var size = common.PageHeaderSize
|
var size = common.PageHeaderSize
|
||||||
for _, inode := range n.inodes {
|
for _, inode := range n.inodes {
|
||||||
size += common.LeafPageElementSize + uintptr(len(inode.key)) + uintptr(len(inode.value))
|
size += common.LeafPageElementSize + uintptr(len(inode.Key())) + uintptr(len(inode.Value()))
|
||||||
|
|
||||||
if inode.flags&common.BucketLeafFlag != 0 {
|
if inode.Flags()&common.BucketLeafFlag != 0 {
|
||||||
return false
|
return false
|
||||||
} else if size > b.maxInlineBucketSize() {
|
} else if size > b.maxInlineBucketSize() {
|
||||||
return false
|
return false
|
||||||
|
|
12
cursor.go
12
cursor.go
|
@ -176,7 +176,7 @@ func (c *Cursor) goToFirstElementOnTheStack() {
|
||||||
// Keep adding pages pointing to the first element to the stack.
|
// Keep adding pages pointing to the first element to the stack.
|
||||||
var pgId common.Pgid
|
var pgId common.Pgid
|
||||||
if ref.node != nil {
|
if ref.node != nil {
|
||||||
pgId = ref.node.inodes[ref.index].pgid
|
pgId = ref.node.inodes[ref.index].Pgid()
|
||||||
} else {
|
} else {
|
||||||
pgId = ref.page.BranchPageElement(uint16(ref.index)).Pgid()
|
pgId = ref.page.BranchPageElement(uint16(ref.index)).Pgid()
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,7 @@ func (c *Cursor) last() {
|
||||||
// Keep adding pages pointing to the last element in the stack.
|
// Keep adding pages pointing to the last element in the stack.
|
||||||
var pgId common.Pgid
|
var pgId common.Pgid
|
||||||
if ref.node != nil {
|
if ref.node != nil {
|
||||||
pgId = ref.node.inodes[ref.index].pgid
|
pgId = ref.node.inodes[ref.index].Pgid()
|
||||||
} else {
|
} else {
|
||||||
pgId = ref.page.BranchPageElement(uint16(ref.index)).Pgid()
|
pgId = ref.page.BranchPageElement(uint16(ref.index)).Pgid()
|
||||||
}
|
}
|
||||||
|
@ -296,7 +296,7 @@ func (c *Cursor) searchNode(key []byte, n *node) {
|
||||||
index := sort.Search(len(n.inodes), func(i int) bool {
|
index := sort.Search(len(n.inodes), func(i int) bool {
|
||||||
// TODO(benbjohnson): Optimize this range search. It's a bit hacky right now.
|
// TODO(benbjohnson): Optimize this range search. It's a bit hacky right now.
|
||||||
// sort.Search() finds the lowest index where f() != -1 but we need the highest index.
|
// sort.Search() finds the lowest index where f() != -1 but we need the highest index.
|
||||||
ret := bytes.Compare(n.inodes[i].key, key)
|
ret := bytes.Compare(n.inodes[i].Key(), key)
|
||||||
if ret == 0 {
|
if ret == 0 {
|
||||||
exact = true
|
exact = true
|
||||||
}
|
}
|
||||||
|
@ -308,7 +308,7 @@ func (c *Cursor) searchNode(key []byte, n *node) {
|
||||||
c.stack[len(c.stack)-1].index = index
|
c.stack[len(c.stack)-1].index = index
|
||||||
|
|
||||||
// Recursively search to the next page.
|
// Recursively search to the next page.
|
||||||
c.search(key, n.inodes[index].pgid)
|
c.search(key, n.inodes[index].Pgid())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cursor) searchPage(key []byte, p *common.Page) {
|
func (c *Cursor) searchPage(key []byte, p *common.Page) {
|
||||||
|
@ -342,7 +342,7 @@ func (c *Cursor) nsearch(key []byte) {
|
||||||
// If we have a node then search its inodes.
|
// If we have a node then search its inodes.
|
||||||
if n != nil {
|
if n != nil {
|
||||||
index := sort.Search(len(n.inodes), func(i int) bool {
|
index := sort.Search(len(n.inodes), func(i int) bool {
|
||||||
return bytes.Compare(n.inodes[i].key, key) != -1
|
return bytes.Compare(n.inodes[i].Key(), key) != -1
|
||||||
})
|
})
|
||||||
e.index = index
|
e.index = index
|
||||||
return
|
return
|
||||||
|
@ -368,7 +368,7 @@ func (c *Cursor) keyValue() ([]byte, []byte, uint32) {
|
||||||
// Retrieve value from node.
|
// Retrieve value from node.
|
||||||
if ref.node != nil {
|
if ref.node != nil {
|
||||||
inode := &ref.node.inodes[ref.index]
|
inode := &ref.node.inodes[ref.index]
|
||||||
return inode.key, inode.value, inode.flags
|
return inode.Key(), inode.Value(), inode.Flags()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Or retrieve value from page.
|
// Or retrieve value from page.
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package common
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
type Inode struct {
|
||||||
|
flags uint32
|
||||||
|
pgid Pgid
|
||||||
|
key []byte
|
||||||
|
value []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type Inodes []Inode
|
||||||
|
|
||||||
|
func (in *Inode) Flags() uint32 {
|
||||||
|
return in.flags
|
||||||
|
}
|
||||||
|
|
||||||
|
func (in *Inode) SetFlags(flags uint32) {
|
||||||
|
in.flags = flags
|
||||||
|
}
|
||||||
|
|
||||||
|
func (in *Inode) Pgid() Pgid {
|
||||||
|
return in.pgid
|
||||||
|
}
|
||||||
|
|
||||||
|
func (in *Inode) SetPgid(id Pgid) {
|
||||||
|
in.pgid = id
|
||||||
|
}
|
||||||
|
|
||||||
|
func (in *Inode) Key() []byte {
|
||||||
|
return in.key
|
||||||
|
}
|
||||||
|
|
||||||
|
func (in *Inode) SetKey(key []byte) {
|
||||||
|
in.key = key
|
||||||
|
}
|
||||||
|
|
||||||
|
func (in *Inode) Value() []byte {
|
||||||
|
return in.value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (in *Inode) SetValue(value []byte) {
|
||||||
|
in.value = value
|
||||||
|
}
|
108
node.go
108
node.go
|
@ -19,7 +19,7 @@ type node struct {
|
||||||
pgid common.Pgid
|
pgid common.Pgid
|
||||||
parent *node
|
parent *node
|
||||||
children nodes
|
children nodes
|
||||||
inodes inodes
|
inodes common.Inodes
|
||||||
}
|
}
|
||||||
|
|
||||||
// root returns the top-level node this node is attached to.
|
// root returns the top-level node this node is attached to.
|
||||||
|
@ -43,7 +43,7 @@ func (n *node) size() int {
|
||||||
sz, elsz := common.PageHeaderSize, n.pageElementSize()
|
sz, elsz := common.PageHeaderSize, n.pageElementSize()
|
||||||
for i := 0; i < len(n.inodes); i++ {
|
for i := 0; i < len(n.inodes); i++ {
|
||||||
item := &n.inodes[i]
|
item := &n.inodes[i]
|
||||||
sz += elsz + uintptr(len(item.key)) + uintptr(len(item.value))
|
sz += elsz + uintptr(len(item.Key())) + uintptr(len(item.Value()))
|
||||||
}
|
}
|
||||||
return int(sz)
|
return int(sz)
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ func (n *node) sizeLessThan(v uintptr) bool {
|
||||||
sz, elsz := common.PageHeaderSize, n.pageElementSize()
|
sz, elsz := common.PageHeaderSize, n.pageElementSize()
|
||||||
for i := 0; i < len(n.inodes); i++ {
|
for i := 0; i < len(n.inodes); i++ {
|
||||||
item := &n.inodes[i]
|
item := &n.inodes[i]
|
||||||
sz += elsz + uintptr(len(item.key)) + uintptr(len(item.value))
|
sz += elsz + uintptr(len(item.Key())) + uintptr(len(item.Value()))
|
||||||
if sz >= v {
|
if sz >= v {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -76,12 +76,12 @@ func (n *node) childAt(index int) *node {
|
||||||
if n.isLeaf {
|
if n.isLeaf {
|
||||||
panic(fmt.Sprintf("invalid childAt(%d) on a leaf node", index))
|
panic(fmt.Sprintf("invalid childAt(%d) on a leaf node", index))
|
||||||
}
|
}
|
||||||
return n.bucket.node(n.inodes[index].pgid, n)
|
return n.bucket.node(n.inodes[index].Pgid(), n)
|
||||||
}
|
}
|
||||||
|
|
||||||
// childIndex returns the index of a given child node.
|
// childIndex returns the index of a given child node.
|
||||||
func (n *node) childIndex(child *node) int {
|
func (n *node) childIndex(child *node) int {
|
||||||
index := sort.Search(len(n.inodes), func(i int) bool { return bytes.Compare(n.inodes[i].key, child.key) != -1 })
|
index := sort.Search(len(n.inodes), func(i int) bool { return bytes.Compare(n.inodes[i].Key(), child.key) != -1 })
|
||||||
return index
|
return index
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,30 +125,30 @@ func (n *node) put(oldKey, newKey, value []byte, pgId common.Pgid, flags uint32)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find insertion index.
|
// Find insertion index.
|
||||||
index := sort.Search(len(n.inodes), func(i int) bool { return bytes.Compare(n.inodes[i].key, oldKey) != -1 })
|
index := sort.Search(len(n.inodes), func(i int) bool { return bytes.Compare(n.inodes[i].Key(), oldKey) != -1 })
|
||||||
|
|
||||||
// Add capacity and shift nodes if we don't have an exact match and need to insert.
|
// Add capacity and shift nodes if we don't have an exact match and need to insert.
|
||||||
exact := len(n.inodes) > 0 && index < len(n.inodes) && bytes.Equal(n.inodes[index].key, oldKey)
|
exact := len(n.inodes) > 0 && index < len(n.inodes) && bytes.Equal(n.inodes[index].Key(), oldKey)
|
||||||
if !exact {
|
if !exact {
|
||||||
n.inodes = append(n.inodes, inode{})
|
n.inodes = append(n.inodes, common.Inode{})
|
||||||
copy(n.inodes[index+1:], n.inodes[index:])
|
copy(n.inodes[index+1:], n.inodes[index:])
|
||||||
}
|
}
|
||||||
|
|
||||||
inode := &n.inodes[index]
|
inode := &n.inodes[index]
|
||||||
inode.flags = flags
|
inode.SetFlags(flags)
|
||||||
inode.key = newKey
|
inode.SetKey(newKey)
|
||||||
inode.value = value
|
inode.SetValue(value)
|
||||||
inode.pgid = pgId
|
inode.SetPgid(pgId)
|
||||||
common.Assert(len(inode.key) > 0, "put: zero-length inode key")
|
common.Assert(len(inode.Key()) > 0, "put: zero-length inode key")
|
||||||
}
|
}
|
||||||
|
|
||||||
// del removes a key from the node.
|
// del removes a key from the node.
|
||||||
func (n *node) del(key []byte) {
|
func (n *node) del(key []byte) {
|
||||||
// Find index of key.
|
// Find index of key.
|
||||||
index := sort.Search(len(n.inodes), func(i int) bool { return bytes.Compare(n.inodes[i].key, key) != -1 })
|
index := sort.Search(len(n.inodes), func(i int) bool { return bytes.Compare(n.inodes[i].Key(), key) != -1 })
|
||||||
|
|
||||||
// Exit if the key isn't found.
|
// Exit if the key isn't found.
|
||||||
if index >= len(n.inodes) || !bytes.Equal(n.inodes[index].key, key) {
|
if index >= len(n.inodes) || !bytes.Equal(n.inodes[index].Key(), key) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,26 +163,26 @@ func (n *node) del(key []byte) {
|
||||||
func (n *node) read(p *common.Page) {
|
func (n *node) read(p *common.Page) {
|
||||||
n.pgid = p.Id()
|
n.pgid = p.Id()
|
||||||
n.isLeaf = (p.Flags() & common.LeafPageFlag) != 0
|
n.isLeaf = (p.Flags() & common.LeafPageFlag) != 0
|
||||||
n.inodes = make(inodes, int(p.Count()))
|
n.inodes = make(common.Inodes, int(p.Count()))
|
||||||
|
|
||||||
for i := 0; i < int(p.Count()); i++ {
|
for i := 0; i < int(p.Count()); i++ {
|
||||||
inode := &n.inodes[i]
|
inode := &n.inodes[i]
|
||||||
if n.isLeaf {
|
if n.isLeaf {
|
||||||
elem := p.LeafPageElement(uint16(i))
|
elem := p.LeafPageElement(uint16(i))
|
||||||
inode.flags = elem.Flags()
|
inode.SetFlags(elem.Flags())
|
||||||
inode.key = elem.Key()
|
inode.SetKey(elem.Key())
|
||||||
inode.value = elem.Value()
|
inode.SetValue(elem.Value())
|
||||||
} else {
|
} else {
|
||||||
elem := p.BranchPageElement(uint16(i))
|
elem := p.BranchPageElement(uint16(i))
|
||||||
inode.pgid = elem.Pgid()
|
inode.SetPgid(elem.Pgid())
|
||||||
inode.key = elem.Key()
|
inode.SetKey(elem.Key())
|
||||||
}
|
}
|
||||||
common.Assert(len(inode.key) > 0, "read: zero-length inode key")
|
common.Assert(len(inode.Key()) > 0, "read: zero-length inode key")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save first key, so we can find the node in the parent when we spill.
|
// Save first key, so we can find the node in the parent when we spill.
|
||||||
if len(n.inodes) > 0 {
|
if len(n.inodes) > 0 {
|
||||||
n.key = n.inodes[0].key
|
n.key = n.inodes[0].Key()
|
||||||
common.Assert(len(n.key) > 0, "read: zero-length node key")
|
common.Assert(len(n.key) > 0, "read: zero-length node key")
|
||||||
} else {
|
} else {
|
||||||
n.key = nil
|
n.key = nil
|
||||||
|
@ -216,11 +216,11 @@ func (n *node) write(p *common.Page) {
|
||||||
// off tracks the offset into p of the start of the next data.
|
// off tracks the offset into p of the start of the next data.
|
||||||
off := unsafe.Sizeof(*p) + n.pageElementSize()*uintptr(len(n.inodes))
|
off := unsafe.Sizeof(*p) + n.pageElementSize()*uintptr(len(n.inodes))
|
||||||
for i, item := range n.inodes {
|
for i, item := range n.inodes {
|
||||||
common.Assert(len(item.key) > 0, "write: zero-length inode key")
|
common.Assert(len(item.Key()) > 0, "write: zero-length inode key")
|
||||||
|
|
||||||
// Create a slice to write into of needed size and advance
|
// Create a slice to write into of needed size and advance
|
||||||
// byte pointer for next iteration.
|
// byte pointer for next iteration.
|
||||||
sz := len(item.key) + len(item.value)
|
sz := len(item.Key()) + len(item.Value())
|
||||||
b := common.UnsafeByteSlice(unsafe.Pointer(p), off, 0, sz)
|
b := common.UnsafeByteSlice(unsafe.Pointer(p), off, 0, sz)
|
||||||
off += uintptr(sz)
|
off += uintptr(sz)
|
||||||
|
|
||||||
|
@ -228,20 +228,20 @@ func (n *node) write(p *common.Page) {
|
||||||
if n.isLeaf {
|
if n.isLeaf {
|
||||||
elem := p.LeafPageElement(uint16(i))
|
elem := p.LeafPageElement(uint16(i))
|
||||||
elem.SetPos(uint32(uintptr(unsafe.Pointer(&b[0])) - uintptr(unsafe.Pointer(elem))))
|
elem.SetPos(uint32(uintptr(unsafe.Pointer(&b[0])) - uintptr(unsafe.Pointer(elem))))
|
||||||
elem.SetFlags(item.flags)
|
elem.SetFlags(item.Flags())
|
||||||
elem.SetKsize(uint32(len(item.key)))
|
elem.SetKsize(uint32(len(item.Key())))
|
||||||
elem.SetVsize(uint32(len(item.value)))
|
elem.SetVsize(uint32(len(item.Value())))
|
||||||
} else {
|
} else {
|
||||||
elem := p.BranchPageElement(uint16(i))
|
elem := p.BranchPageElement(uint16(i))
|
||||||
elem.SetPos(uint32(uintptr(unsafe.Pointer(&b[0])) - uintptr(unsafe.Pointer(elem))))
|
elem.SetPos(uint32(uintptr(unsafe.Pointer(&b[0])) - uintptr(unsafe.Pointer(elem))))
|
||||||
elem.SetKsize(uint32(len(item.key)))
|
elem.SetKsize(uint32(len(item.Key())))
|
||||||
elem.SetPgid(item.pgid)
|
elem.SetPgid(item.Pgid())
|
||||||
common.Assert(elem.Pgid() != p.Id(), "write: circular dependency occurred")
|
common.Assert(elem.Pgid() != p.Id(), "write: circular dependency occurred")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write data for the element to the end of the page.
|
// Write data for the element to the end of the page.
|
||||||
l := copy(b, item.key)
|
l := copy(b, item.Key())
|
||||||
copy(b[l:], item.value)
|
copy(b[l:], item.Value())
|
||||||
}
|
}
|
||||||
|
|
||||||
// DEBUG ONLY: n.dump()
|
// DEBUG ONLY: n.dump()
|
||||||
|
@ -321,7 +321,7 @@ func (n *node) splitIndex(threshold int) (index, sz uintptr) {
|
||||||
for i := 0; i < len(n.inodes)-common.MinKeysPerPage; i++ {
|
for i := 0; i < len(n.inodes)-common.MinKeysPerPage; i++ {
|
||||||
index = uintptr(i)
|
index = uintptr(i)
|
||||||
inode := n.inodes[i]
|
inode := n.inodes[i]
|
||||||
elsize := n.pageElementSize() + uintptr(len(inode.key)) + uintptr(len(inode.value))
|
elsize := n.pageElementSize() + uintptr(len(inode.Key())) + uintptr(len(inode.Value()))
|
||||||
|
|
||||||
// If we have at least the minimum number of keys and adding another
|
// If we have at least the minimum number of keys and adding another
|
||||||
// node would put us over the threshold then exit and return.
|
// node would put us over the threshold then exit and return.
|
||||||
|
@ -384,11 +384,11 @@ func (n *node) spill() error {
|
||||||
if node.parent != nil {
|
if node.parent != nil {
|
||||||
var key = node.key
|
var key = node.key
|
||||||
if key == nil {
|
if key == nil {
|
||||||
key = node.inodes[0].key
|
key = node.inodes[0].Key()
|
||||||
}
|
}
|
||||||
|
|
||||||
node.parent.put(key, node.inodes[0].key, nil, node.pgid, 0)
|
node.parent.put(key, node.inodes[0].Key(), nil, node.pgid, 0)
|
||||||
node.key = node.inodes[0].key
|
node.key = node.inodes[0].Key()
|
||||||
common.Assert(len(node.key) > 0, "spill: zero-length node key")
|
common.Assert(len(node.key) > 0, "spill: zero-length node key")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,14 +428,14 @@ func (n *node) rebalance() {
|
||||||
// If root node is a branch and only has one node then collapse it.
|
// If root node is a branch and only has one node then collapse it.
|
||||||
if !n.isLeaf && len(n.inodes) == 1 {
|
if !n.isLeaf && len(n.inodes) == 1 {
|
||||||
// Move root's child up.
|
// Move root's child up.
|
||||||
child := n.bucket.node(n.inodes[0].pgid, n)
|
child := n.bucket.node(n.inodes[0].Pgid(), n)
|
||||||
n.isLeaf = child.isLeaf
|
n.isLeaf = child.isLeaf
|
||||||
n.inodes = child.inodes[:]
|
n.inodes = child.inodes[:]
|
||||||
n.children = child.children
|
n.children = child.children
|
||||||
|
|
||||||
// Reparent all child nodes being moved.
|
// Reparent all child nodes being moved.
|
||||||
for _, inode := range n.inodes {
|
for _, inode := range n.inodes {
|
||||||
if child, ok := n.bucket.nodes[inode.pgid]; ok {
|
if child, ok := n.bucket.nodes[inode.Pgid()]; ok {
|
||||||
child.parent = n
|
child.parent = n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -474,7 +474,7 @@ func (n *node) rebalance() {
|
||||||
if useNextSibling {
|
if useNextSibling {
|
||||||
// Reparent all child nodes being moved.
|
// Reparent all child nodes being moved.
|
||||||
for _, inode := range target.inodes {
|
for _, inode := range target.inodes {
|
||||||
if child, ok := n.bucket.nodes[inode.pgid]; ok {
|
if child, ok := n.bucket.nodes[inode.Pgid()]; ok {
|
||||||
child.parent.removeChild(child)
|
child.parent.removeChild(child)
|
||||||
child.parent = n
|
child.parent = n
|
||||||
child.parent.children = append(child.parent.children, child)
|
child.parent.children = append(child.parent.children, child)
|
||||||
|
@ -490,7 +490,7 @@ func (n *node) rebalance() {
|
||||||
} else {
|
} else {
|
||||||
// Reparent all child nodes being moved.
|
// Reparent all child nodes being moved.
|
||||||
for _, inode := range n.inodes {
|
for _, inode := range n.inodes {
|
||||||
if child, ok := n.bucket.nodes[inode.pgid]; ok {
|
if child, ok := n.bucket.nodes[inode.Pgid()]; ok {
|
||||||
child.parent.removeChild(child)
|
child.parent.removeChild(child)
|
||||||
child.parent = target
|
child.parent = target
|
||||||
child.parent.children = append(child.parent.children, child)
|
child.parent.children = append(child.parent.children, child)
|
||||||
|
@ -533,14 +533,14 @@ func (n *node) dereference() {
|
||||||
for i := range n.inodes {
|
for i := range n.inodes {
|
||||||
inode := &n.inodes[i]
|
inode := &n.inodes[i]
|
||||||
|
|
||||||
key := make([]byte, len(inode.key))
|
key := make([]byte, len(inode.Key()))
|
||||||
copy(key, inode.key)
|
copy(key, inode.Key())
|
||||||
inode.key = key
|
inode.SetKey(key)
|
||||||
common.Assert(len(inode.key) > 0, "dereference: zero-length inode key")
|
common.Assert(len(inode.Key()) > 0, "dereference: zero-length inode key")
|
||||||
|
|
||||||
value := make([]byte, len(inode.value))
|
value := make([]byte, len(inode.Value()))
|
||||||
copy(value, inode.value)
|
copy(value, inode.Value())
|
||||||
inode.value = value
|
inode.SetValue(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recursively dereference children.
|
// Recursively dereference children.
|
||||||
|
@ -596,17 +596,5 @@ type nodes []*node
|
||||||
func (s nodes) Len() int { return len(s) }
|
func (s nodes) Len() int { return len(s) }
|
||||||
func (s nodes) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
func (s nodes) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||||
func (s nodes) Less(i, j int) bool {
|
func (s nodes) Less(i, j int) bool {
|
||||||
return bytes.Compare(s[i].inodes[0].key, s[j].inodes[0].key) == -1
|
return bytes.Compare(s[i].inodes[0].Key(), s[j].inodes[0].Key()) == -1
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
|
||||||
type inode struct {
|
|
||||||
flags uint32
|
|
||||||
pgid common.Pgid
|
|
||||||
key []byte
|
|
||||||
value []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type inodes []inode
|
|
||||||
|
|
30
node_test.go
30
node_test.go
|
@ -11,7 +11,7 @@ import (
|
||||||
func TestNode_put(t *testing.T) {
|
func TestNode_put(t *testing.T) {
|
||||||
m := &common.Meta{}
|
m := &common.Meta{}
|
||||||
m.SetPgid(1)
|
m.SetPgid(1)
|
||||||
n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{meta: m}}}
|
n := &node{inodes: make(common.Inodes, 0), bucket: &Bucket{tx: &Tx{meta: m}}}
|
||||||
n.put([]byte("baz"), []byte("baz"), []byte("2"), 0, 0)
|
n.put([]byte("baz"), []byte("baz"), []byte("2"), 0, 0)
|
||||||
n.put([]byte("foo"), []byte("foo"), []byte("0"), 0, 0)
|
n.put([]byte("foo"), []byte("foo"), []byte("0"), 0, 0)
|
||||||
n.put([]byte("bar"), []byte("bar"), []byte("1"), 0, 0)
|
n.put([]byte("bar"), []byte("bar"), []byte("1"), 0, 0)
|
||||||
|
@ -20,17 +20,17 @@ func TestNode_put(t *testing.T) {
|
||||||
if len(n.inodes) != 3 {
|
if len(n.inodes) != 3 {
|
||||||
t.Fatalf("exp=3; got=%d", len(n.inodes))
|
t.Fatalf("exp=3; got=%d", len(n.inodes))
|
||||||
}
|
}
|
||||||
if k, v := n.inodes[0].key, n.inodes[0].value; string(k) != "bar" || string(v) != "1" {
|
if k, v := n.inodes[0].Key(), n.inodes[0].Value(); string(k) != "bar" || string(v) != "1" {
|
||||||
t.Fatalf("exp=<bar,1>; got=<%s,%s>", k, v)
|
t.Fatalf("exp=<bar,1>; got=<%s,%s>", k, v)
|
||||||
}
|
}
|
||||||
if k, v := n.inodes[1].key, n.inodes[1].value; string(k) != "baz" || string(v) != "2" {
|
if k, v := n.inodes[1].Key(), n.inodes[1].Value(); string(k) != "baz" || string(v) != "2" {
|
||||||
t.Fatalf("exp=<baz,2>; got=<%s,%s>", k, v)
|
t.Fatalf("exp=<baz,2>; got=<%s,%s>", k, v)
|
||||||
}
|
}
|
||||||
if k, v := n.inodes[2].key, n.inodes[2].value; string(k) != "foo" || string(v) != "3" {
|
if k, v := n.inodes[2].Key(), n.inodes[2].Value(); string(k) != "foo" || string(v) != "3" {
|
||||||
t.Fatalf("exp=<foo,3>; got=<%s,%s>", k, v)
|
t.Fatalf("exp=<foo,3>; got=<%s,%s>", k, v)
|
||||||
}
|
}
|
||||||
if n.inodes[2].flags != uint32(common.LeafPageFlag) {
|
if n.inodes[2].Flags() != uint32(common.LeafPageFlag) {
|
||||||
t.Fatalf("not a leaf: %d", n.inodes[2].flags)
|
t.Fatalf("not a leaf: %d", n.inodes[2].Flags())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,10 +64,10 @@ func TestNode_read_LeafPage(t *testing.T) {
|
||||||
if len(n.inodes) != 2 {
|
if len(n.inodes) != 2 {
|
||||||
t.Fatalf("exp=2; got=%d", len(n.inodes))
|
t.Fatalf("exp=2; got=%d", len(n.inodes))
|
||||||
}
|
}
|
||||||
if k, v := n.inodes[0].key, n.inodes[0].value; string(k) != "bar" || string(v) != "fooz" {
|
if k, v := n.inodes[0].Key(), n.inodes[0].Value(); string(k) != "bar" || string(v) != "fooz" {
|
||||||
t.Fatalf("exp=<bar,fooz>; got=<%s,%s>", k, v)
|
t.Fatalf("exp=<bar,fooz>; got=<%s,%s>", k, v)
|
||||||
}
|
}
|
||||||
if k, v := n.inodes[1].key, n.inodes[1].value; string(k) != "helloworld" || string(v) != "bye" {
|
if k, v := n.inodes[1].Key(), n.inodes[1].Value(); string(k) != "helloworld" || string(v) != "bye" {
|
||||||
t.Fatalf("exp=<helloworld,bye>; got=<%s,%s>", k, v)
|
t.Fatalf("exp=<helloworld,bye>; got=<%s,%s>", k, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ func TestNode_write_LeafPage(t *testing.T) {
|
||||||
// Create a node.
|
// Create a node.
|
||||||
m := &common.Meta{}
|
m := &common.Meta{}
|
||||||
m.SetPgid(1)
|
m.SetPgid(1)
|
||||||
n := &node{isLeaf: true, inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{db: &DB{}, meta: m}}}
|
n := &node{isLeaf: true, inodes: make(common.Inodes, 0), bucket: &Bucket{tx: &Tx{db: &DB{}, meta: m}}}
|
||||||
n.put([]byte("susy"), []byte("susy"), []byte("que"), 0, 0)
|
n.put([]byte("susy"), []byte("susy"), []byte("que"), 0, 0)
|
||||||
n.put([]byte("ricki"), []byte("ricki"), []byte("lake"), 0, 0)
|
n.put([]byte("ricki"), []byte("ricki"), []byte("lake"), 0, 0)
|
||||||
n.put([]byte("john"), []byte("john"), []byte("johnson"), 0, 0)
|
n.put([]byte("john"), []byte("john"), []byte("johnson"), 0, 0)
|
||||||
|
@ -95,13 +95,13 @@ func TestNode_write_LeafPage(t *testing.T) {
|
||||||
if len(n2.inodes) != 3 {
|
if len(n2.inodes) != 3 {
|
||||||
t.Fatalf("exp=3; got=%d", len(n2.inodes))
|
t.Fatalf("exp=3; got=%d", len(n2.inodes))
|
||||||
}
|
}
|
||||||
if k, v := n2.inodes[0].key, n2.inodes[0].value; string(k) != "john" || string(v) != "johnson" {
|
if k, v := n2.inodes[0].Key(), n2.inodes[0].Value(); string(k) != "john" || string(v) != "johnson" {
|
||||||
t.Fatalf("exp=<john,johnson>; got=<%s,%s>", k, v)
|
t.Fatalf("exp=<john,johnson>; got=<%s,%s>", k, v)
|
||||||
}
|
}
|
||||||
if k, v := n2.inodes[1].key, n2.inodes[1].value; string(k) != "ricki" || string(v) != "lake" {
|
if k, v := n2.inodes[1].Key(), n2.inodes[1].Value(); string(k) != "ricki" || string(v) != "lake" {
|
||||||
t.Fatalf("exp=<ricki,lake>; got=<%s,%s>", k, v)
|
t.Fatalf("exp=<ricki,lake>; got=<%s,%s>", k, v)
|
||||||
}
|
}
|
||||||
if k, v := n2.inodes[2].key, n2.inodes[2].value; string(k) != "susy" || string(v) != "que" {
|
if k, v := n2.inodes[2].Key(), n2.inodes[2].Value(); string(k) != "susy" || string(v) != "que" {
|
||||||
t.Fatalf("exp=<susy,que>; got=<%s,%s>", k, v)
|
t.Fatalf("exp=<susy,que>; got=<%s,%s>", k, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ func TestNode_split(t *testing.T) {
|
||||||
// Create a node.
|
// Create a node.
|
||||||
m := &common.Meta{}
|
m := &common.Meta{}
|
||||||
m.SetPgid(1)
|
m.SetPgid(1)
|
||||||
n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{db: &DB{}, meta: m}}}
|
n := &node{inodes: make(common.Inodes, 0), bucket: &Bucket{tx: &Tx{db: &DB{}, meta: m}}}
|
||||||
n.put([]byte("00000001"), []byte("00000001"), []byte("0123456701234567"), 0, 0)
|
n.put([]byte("00000001"), []byte("00000001"), []byte("0123456701234567"), 0, 0)
|
||||||
n.put([]byte("00000002"), []byte("00000002"), []byte("0123456701234567"), 0, 0)
|
n.put([]byte("00000002"), []byte("00000002"), []byte("0123456701234567"), 0, 0)
|
||||||
n.put([]byte("00000003"), []byte("00000003"), []byte("0123456701234567"), 0, 0)
|
n.put([]byte("00000003"), []byte("00000003"), []byte("0123456701234567"), 0, 0)
|
||||||
|
@ -138,7 +138,7 @@ func TestNode_split_MinKeys(t *testing.T) {
|
||||||
// Create a node.
|
// Create a node.
|
||||||
m := &common.Meta{}
|
m := &common.Meta{}
|
||||||
m.SetPgid(1)
|
m.SetPgid(1)
|
||||||
n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{db: &DB{}, meta: m}}}
|
n := &node{inodes: make(common.Inodes, 0), bucket: &Bucket{tx: &Tx{db: &DB{}, meta: m}}}
|
||||||
n.put([]byte("00000001"), []byte("00000001"), []byte("0123456701234567"), 0, 0)
|
n.put([]byte("00000001"), []byte("00000001"), []byte("0123456701234567"), 0, 0)
|
||||||
n.put([]byte("00000002"), []byte("00000002"), []byte("0123456701234567"), 0, 0)
|
n.put([]byte("00000002"), []byte("00000002"), []byte("0123456701234567"), 0, 0)
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ func TestNode_split_SinglePage(t *testing.T) {
|
||||||
// Create a node.
|
// Create a node.
|
||||||
m := &common.Meta{}
|
m := &common.Meta{}
|
||||||
m.SetPgid(1)
|
m.SetPgid(1)
|
||||||
n := &node{inodes: make(inodes, 0), bucket: &Bucket{tx: &Tx{db: &DB{}, meta: m}}}
|
n := &node{inodes: make(common.Inodes, 0), bucket: &Bucket{tx: &Tx{db: &DB{}, meta: m}}}
|
||||||
n.put([]byte("00000001"), []byte("00000001"), []byte("0123456701234567"), 0, 0)
|
n.put([]byte("00000001"), []byte("00000001"), []byte("0123456701234567"), 0, 0)
|
||||||
n.put([]byte("00000002"), []byte("00000002"), []byte("0123456701234567"), 0, 0)
|
n.put([]byte("00000002"), []byte("00000002"), []byte("0123456701234567"), 0, 0)
|
||||||
n.put([]byte("00000003"), []byte("00000003"), []byte("0123456701234567"), 0, 0)
|
n.put([]byte("00000003"), []byte("00000003"), []byte("0123456701234567"), 0, 0)
|
||||||
|
|
Loading…
Reference in New Issue