第五节 叶子节点页
叶子节点主要用来存储实际的数据,也就是key+value了。下面看看具体的key+value是如何设计的。
在boltdb中,每一对key/value在存储时,都有一份元素元信息,也就是leafPageElement。其中定义了key的长度、value的长度、具体存储的值距离元信息的偏移位置pos。
// leafPageElement represents a node on a leaf page.
// 叶子节点既存储key,也存储value
type leafPageElement struct {
flags uint32 //该值主要用来区分,是子桶叶子节点元素还是普通的key/value叶子节点元素。flags值为1时表示子桶。否则为key/value
pos uint32
ksize uint32
vsize uint32
}
// 叶子节点的key
// key returns a byte slice of the node key.
func (n *leafPageElement) key() []byte {
buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
// pos~ksize
return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos]))[:n.ksize:n.ksize]
}
// 叶子节点的value
// value returns a byte slice of the node value.
func (n *leafPageElement) value() []byte {
buf := (*[maxAllocSize]byte)(unsafe.Pointer(n))
// key:pos~ksize
// value:pos+ksize~pos+ksize+vsize
return (*[maxAllocSize]byte)(unsafe.Pointer(&buf[n.pos+n.ksize]))[:n.vsize:n.vsize]
}
下面是具体在叶子节点的page中获取下标为index的某个key/value的元信息。根据其元信息,就可以进一步获取其存储的key和value的值了,具体方法可以看上面的key()和value()
// leafPageElement retrieves the leaf node by index
func (p *page) leafPageElement(index uint16) *leafPageElement {
n := &((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[index]
// 最原始的指针:unsafe.Pointer(&p.ptr)
// 将其转为(*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr))
// 然后再取第index个元素 ((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[index]
// 最后返回该元素指针 &((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[index]
// ((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))
// (*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr))==>[]leafPageElement
// &leafElements[index]
return n
}
// leafPageElements retrieves a list of leaf nodes.
func (p *page) leafPageElements() []leafPageElement {
if p.count == 0 {
return nil
}
return ((*[0x7FFFFFF]leafPageElement)(unsafe.Pointer(&p.ptr)))[:]
}
下图展现的是叶子节点存储方式。
其具体叶子节点页page转换成node时的转变过程如同分支节点转换的方法一样,此处就不做赘述,可以参考2.1.3节介绍的read()和write()方法
当前内容版权归 jaydenwen123 或其关联方所有,如需对内容或内容相关联开源项目进行关注与资助,请访问 jaydenwen123 .