feat(gobplustree): 添加页面结构定义与反序列化逻辑
新增了 B+ 树中页面的基本结构体定义,包括页头、单元格等。同时实现了 页头和整个页面数据的反序列化方法,用于从字节数据中解析出页面对象。 该功能为后续存储引擎的读取和管理页面提供基础支持。
This commit is contained in:
parent
e6ed39f0df
commit
96ba95f1be
|
|
@ -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
|
||||
}
|
||||
Loading…
Reference in New Issue