package core import ( "TsDB2/DB/core/page" "unsafe" ) type HeapInfo struct { Hdr page.PageHdr Data [PageSize - page.PageHdrSize]byte } type HeapPage struct { Info HeapInfo handle page.HandleDb // 回调函数 } // ============================================================================= // HeapPage 核心自治方法(所有操作全封装在这里,无管理器) // ============================================================================= // NewHeapPage 创建一个全新的堆页(开辟函数) func NewHeapPage(handle page.HandleDb, pageType page.PageType) *HeapPage { hp := &HeapPage{handle: handle} hp.Info.Hdr.Type = pageType // 固定=堆页 hp.Info.Hdr.PageID = handle.NewPage() // 自动分配新页ID hp.Info.Hdr.UseSize = page.PageHdrSize // 初始已用 = 页头大小 return hp } // LoadHeapPage 从磁盘加载已存在的堆页 func LoadHeapPage(handle page.HandleDb, pageID uint32) (*HeapPage, error) { buf := make([]byte, PageSize) if err := handle.ReadPage(pageID, buf); err != nil { return nil, err } return &HeapPage{ Info: HeapInfo{ Hdr: *page.HdrOf(buf), Data: ([PageSize - page.PageHdrSize]byte)(buf[page.PageHdrSize:]), }, handle: handle, }, nil } // ----------------------- // 修复完成!Alloc 返回 【数据区内部偏移】(去掉页头) // ----------------------- //func (hp *HeapPage) Alloc(need uint32) (allocPageID uint32, allocOff uint32, err error) { // if need > PageSize-page.PageHdrSize { // return 0, 0, ErrHeapPageTooLarge // } // // // 1. 计算剩余空间(只算数据区) // usedData := hp.Info.Hdr.UseSize - page.PageHdrSize // 已用数据区大小 // freeData := (PageSize - page.PageHdrSize) - usedData // 剩余数据区大小 // // // 空间足够 → 分配【数据区偏移】 // if freeData >= need { // // 🔥 核心修复:返回的是 Data 数组的偏移(去掉页头) // off := usedData // hp.Info.Hdr.UseSize += need // _ = hp.Save() // return hp.Info.Hdr.PageID, off, nil // } // // // 2. 空间不足 → 创建新页 // newHp := NewHeapPage(hp.handle, hp.Info.Hdr.Type) // // // 维护页链 // hp.Info.Hdr.NextPage = newHp.Info.Hdr.PageID // newHp.Info.Hdr.PrePage = hp.Info.Hdr.PageID // _ = hp.Save() // // // 3. 新页分配:返回【数据区偏移 0】 // newOff := uint32(0) // newHp.Info.Hdr.UseSize += need // _ = newHp.Save() // // return newHp.Info.Hdr.PageID, newOff, nil //} func (hp *HeapPage) Alloc(need uint32) (allocPageID uint32, allocOff uint32, err error) { // 安全检查:申请空间不能超过单页最大容量 if need > PageSize-page.PageHdrSize { return 0, 0, ErrHeapPageTooLarge } // 1. 当前页剩余空间足够 → 直接分配【页内物理偏移】 free := PageSize - hp.Info.Hdr.UseSize if free >= need { // ✅ 直接返回当前页的物理偏移(包含页头,真实地址) off := hp.Info.Hdr.UseSize hp.Info.Hdr.UseSize += need hp.Info.Hdr.AddRef() // 本页新增一个引用 _ = hp.Save() return hp.Info.Hdr.PageID, off, nil } // 2. 空间不足 → 创建新堆页 newHp := NewHeapPage(hp.handle, hp.Info.Hdr.Type) // 维护页双向链 hp.Info.Hdr.NextPage = newHp.Info.Hdr.PageID newHp.Info.Hdr.PrePage = hp.Info.Hdr.PageID _ = hp.Save() // 3. 新页分配:返回新页的物理偏移(PageHdrSize,真实起始地址) newOff := newHp.Info.Hdr.UseSize // = page.PageHdrSize newHp.Info.Hdr.UseSize += need newHp.Info.Hdr.AddRef() // 新页的第一个引用 _ = newHp.Save() return newHp.Info.Hdr.PageID, newOff, nil } // Save 自动保存当前堆页到磁盘 func (hp *HeapPage) Save() error { buf := make([]byte, PageSize) // 写入页头 *page.HdrOf(buf) = hp.Info.Hdr // 写入数据区 copy(buf[page.PageHdrSize:], hp.Info.Data[:]) return hp.handle.SavePage(hp.Info.Hdr.PageID, buf) } // Get 返回 HeapInfo 的零拷贝字节切片(直接指向内部内存) func (hp *HeapPage) Get() []byte { size := unsafe.Sizeof(hp.Info) ptr := (*byte)(unsafe.Pointer(&hp.Info)) return unsafe.Slice(ptr, size) }