diff --git a/page.go b/page.go index 80ce356..1bba65a 100644 --- a/page.go +++ b/page.go @@ -48,11 +48,17 @@ func DeSerializePageHead(data []byte) (*PageHead, error) { FirstFreeOffset: FirstFreeOffset, }, nil } + +// DeSerializePage 从字节数据中反序列化Page结构 +// data: 包含页面数据的字节切片 +// 返回值: 解析出的Page指针和可能的错误 func DeSerializePage(data []byte) (*Page, error) { head, err := DeSerializePageHead(data[0:BlockFileHeaderSize]) if err != nil { return nil, err } + + // 如果没有cell,直接返回空的cells数组 if head.CellCount == 0 { return &Page{ PageHead: head, @@ -60,8 +66,10 @@ func DeSerializePage(data []byte) (*Page, error) { data: data, }, nil } + cells := make([]*Cell, head.CellCount) - // find cell offset array start + + // 查找cell偏移数组的起始位置 cellPOffset := 0 for i := 17; i < BlockFilePageSize; i++ { t := binary.LittleEndian.Uint32(data[i : i+4]) @@ -74,26 +82,69 @@ func DeSerializePage(data []byte) (*Page, error) { if cellPOffset == 0 { return nil, errors.New("invalid page") } + + previousCellOffset := 0 currentFreeOffset := head.FirstFreeOffset + + // 遍历所有cell,解析每个cell的信息 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 + + cellSize := 0 + // cell if from end to start + if i == 0 { + cellSize = BlockFilePageSize - int(cellOffset) + } else { + cellSize = int(cellOffset) - int(previousCellOffset) + } + cells[i] = &Cell{ IsFree: false, NextFreeOffset: 0, ActualSize: int(cellSize), Start: Offset(cellOffset), } + + // 检查当前cell是否为空闲cell if cellOffset == uint32(currentFreeOffset) { cells[i].IsFree = true cells[i].NextFreeOffset = Offset(binary.LittleEndian.Uint32(data[cellOffset+4 : cellOffset+8])) currentFreeOffset = cells[i].NextFreeOffset } + previousCellOffset = int(cellOffset) } + return &Page{ PageHead: head, Cells: cells, data: data, }, nil } + +func (p *Page) Serialize() []byte { + // 写入PageHead + binary.LittleEndian.PutUint64(p.data[0:8], uint64(p.PageId)) + p.data[8] = byte(p.Type) + p.data[9] = byte(p.CellCount) + p.data[10] = byte(p.FirstFreeOffset) + + // 写入Cell偏移数组 + lastCellOffset := p.Cells[p.CellCount-1].Start + cellOffsets := make([]byte, p.CellCount*4) + for i, cell := range p.Cells { + binary.LittleEndian.PutUint32(cellOffsets[i*4:i*4+4], uint32(cell.Start)) + } + copy(p.data[int(lastCellOffset)-len(cellOffsets):lastCellOffset], cellOffsets) + return p.data +} + +func (p *Page) GetCell(index int) *Cell { + return p.Cells[index] +} +func (p *Page) GetCellData(cell *Cell) []byte { + return p.data[cell.Start : cell.Start+Offset(cell.ActualSize)] +} + +func (p *Page) WriteNewCell(data []byte) (*Cell, error) { + +}