Files
srdb/btree/reader.go
bourdon ae87c38776 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
2025-10-08 06:38:28 +08:00

107 lines
2.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)
}
}
}