Initial commit: SRDB - High-performance LSM-Tree database
- Core engine with MemTable, SST, WAL - B+Tree indexing for SST files - Leveled compaction strategy - Multi-table database management - Schema validation and secondary indexes - Query builder with complex conditions - Web UI with HTMX for data visualization - Command-line tools for diagnostics
This commit is contained in:
106
btree/reader.go
Normal file
106
btree/reader.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package btree
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/edsrzf/mmap-go"
|
||||
)
|
||||
|
||||
// Reader 用于查询 B+Tree (mmap)
|
||||
type Reader struct {
|
||||
mmap mmap.MMap
|
||||
rootOffset int64
|
||||
}
|
||||
|
||||
// NewReader 创建查询器
|
||||
func NewReader(mmap mmap.MMap, rootOffset int64) *Reader {
|
||||
return &Reader{
|
||||
mmap: mmap,
|
||||
rootOffset: rootOffset,
|
||||
}
|
||||
}
|
||||
|
||||
// Get 查询 key,返回数据位置
|
||||
func (r *Reader) Get(key int64) (dataOffset int64, dataSize int32, found bool) {
|
||||
if r.rootOffset == 0 {
|
||||
return 0, 0, false
|
||||
}
|
||||
|
||||
nodeOffset := r.rootOffset
|
||||
|
||||
for {
|
||||
// 读取节点 (零拷贝)
|
||||
if nodeOffset+NodeSize > int64(len(r.mmap)) {
|
||||
return 0, 0, false
|
||||
}
|
||||
|
||||
nodeData := r.mmap[nodeOffset : nodeOffset+NodeSize]
|
||||
node := Unmarshal(nodeData)
|
||||
|
||||
if node == nil {
|
||||
return 0, 0, false
|
||||
}
|
||||
|
||||
// 叶子节点
|
||||
if node.NodeType == NodeTypeLeaf {
|
||||
// 二分查找
|
||||
idx := sort.Search(len(node.Keys), func(i int) bool {
|
||||
return node.Keys[i] >= key
|
||||
})
|
||||
if idx < len(node.Keys) && node.Keys[idx] == key {
|
||||
return node.DataOffsets[idx], node.DataSizes[idx], true
|
||||
}
|
||||
return 0, 0, false
|
||||
}
|
||||
|
||||
// 内部节点,继续向下
|
||||
// keys[i] 是分隔符,children[i] 包含 < keys[i] 的数据
|
||||
// children[i+1] 包含 >= keys[i] 的数据
|
||||
idx := sort.Search(len(node.Keys), func(i int) bool {
|
||||
return node.Keys[i] > key
|
||||
})
|
||||
// idx 现在指向第一个 > key 的位置
|
||||
// 我们应该走 children[idx]
|
||||
if idx >= len(node.Children) {
|
||||
idx = len(node.Children) - 1
|
||||
}
|
||||
nodeOffset = node.Children[idx]
|
||||
}
|
||||
}
|
||||
|
||||
// GetAllKeys 获取 B+Tree 中所有的 key(按顺序)
|
||||
func (r *Reader) GetAllKeys() []int64 {
|
||||
if r.rootOffset == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var keys []int64
|
||||
r.traverseLeafNodes(r.rootOffset, func(node *BTreeNode) {
|
||||
keys = append(keys, node.Keys...)
|
||||
})
|
||||
return keys
|
||||
}
|
||||
|
||||
// traverseLeafNodes 遍历所有叶子节点
|
||||
func (r *Reader) traverseLeafNodes(nodeOffset int64, callback func(*BTreeNode)) {
|
||||
if nodeOffset+NodeSize > int64(len(r.mmap)) {
|
||||
return
|
||||
}
|
||||
|
||||
nodeData := r.mmap[nodeOffset : nodeOffset+NodeSize]
|
||||
node := Unmarshal(nodeData)
|
||||
|
||||
if node == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if node.NodeType == NodeTypeLeaf {
|
||||
// 叶子节点,执行回调
|
||||
callback(node)
|
||||
} else {
|
||||
// 内部节点,递归遍历所有子节点
|
||||
for _, childOffset := range node.Children {
|
||||
r.traverseLeafNodes(childOffset, callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user