feat(gobplustree): 添加页面结构定义与反序列化逻辑

新增了 B+ 树中页面的基本结构体定义,包括页头、单元格等。同时实现了
页头和整个页面数据的反序列化方法,用于从字节数据中解析出页面对象。
该功能为后续存储引擎的读取和管理页面提供基础支持。
This commit is contained in:
程广 2025-11-09 18:19:05 +08:00
parent e6ed39f0df
commit 96ba95f1be
1 changed files with 99 additions and 0 deletions

99
page.go Normal file
View File

@ -0,0 +1,99 @@
package gobplustree
import (
"encoding/binary"
"errors"
)
type PageType int8
type Offset uint32
const (
PageTypeLeaf PageType = iota
PageTypeInternal
)
const (
CellHeaderSize = 17
)
type PageHead struct {
PageId int64
Type PageType
CellCount int
FirstFreeOffset Offset
}
type Cell struct {
IsFree bool
NextFreeOffset Offset
ActualSize int
Start Offset
}
type Page struct {
*PageHead
Cells []*Cell
data []byte
}
func DeSerializePageHead(data []byte) (*PageHead, error) {
PageId := binary.LittleEndian.Uint64(data[0:8])
Type := PageType(data[8])
CellCount := int(data[9])
FirstFreeOffset := Offset(data[10])
return &PageHead{
PageId: int64(PageId),
Type: Type,
CellCount: CellCount,
FirstFreeOffset: FirstFreeOffset,
}, nil
}
func DeSerializePage(data []byte) (*Page, error) {
head, err := DeSerializePageHead(data[0:BlockFileHeaderSize])
if err != nil {
return nil, err
}
if head.CellCount == 0 {
return &Page{
PageHead: head,
Cells: []*Cell{},
data: data,
}, nil
}
cells := make([]*Cell, head.CellCount)
// find cell offset array start
cellPOffset := 0
for i := 17; i < BlockFilePageSize; i++ {
t := binary.LittleEndian.Uint32(data[i : i+4])
if t != 0 {
cellPOffset = i
break
}
}
if cellPOffset == 0 {
return nil, errors.New("invalid page")
}
currentFreeOffset := head.FirstFreeOffset
for i := 0; i < head.CellCount; i++ {
cellOffset := binary.LittleEndian.Uint32(data[cellPOffset+i*4 : cellPOffset+i*4+4])
nextOffSet := binary.LittleEndian.Uint32(data[cellOffset : cellOffset+4])
cellSize := nextOffSet - cellOffset
cells[i] = &Cell{
IsFree: false,
NextFreeOffset: 0,
ActualSize: int(cellSize),
Start: Offset(cellOffset),
}
if cellOffset == uint32(currentFreeOffset) {
cells[i].IsFree = true
cells[i].NextFreeOffset = Offset(binary.LittleEndian.Uint32(data[cellOffset+4 : cellOffset+8]))
currentFreeOffset = cells[i].NextFreeOffset
}
}
return &Page{
PageHead: head,
Cells: cells,
data: data,
}, nil
}