HeapPage.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. package core
  2. import (
  3. "TsDB2/DB/core/page"
  4. "unsafe"
  5. )
  6. type HeapInfo struct {
  7. Hdr page.PageHdr
  8. Data [PageSize - page.PageHdrSize]byte
  9. }
  10. type HeapPage struct {
  11. Info HeapInfo
  12. handle page.HandleDb // 回调函数
  13. }
  14. // =============================================================================
  15. // HeapPage 核心自治方法(所有操作全封装在这里,无管理器)
  16. // =============================================================================
  17. // NewHeapPage 创建一个全新的堆页(开辟函数)
  18. func NewHeapPage(handle page.HandleDb, pageType page.PageType) *HeapPage {
  19. hp := &HeapPage{handle: handle}
  20. hp.Info.Hdr.Type = pageType // 固定=堆页
  21. hp.Info.Hdr.PageID = handle.NewPage() // 自动分配新页ID
  22. hp.Info.Hdr.UseSize = page.PageHdrSize // 初始已用 = 页头大小
  23. return hp
  24. }
  25. // LoadHeapPage 从磁盘加载已存在的堆页
  26. func LoadHeapPage(handle page.HandleDb, pageID uint32) (*HeapPage, error) {
  27. buf := make([]byte, PageSize)
  28. if err := handle.ReadPage(pageID, buf); err != nil {
  29. return nil, err
  30. }
  31. return &HeapPage{
  32. Info: HeapInfo{
  33. Hdr: *(*page.PageHdr)(unsafe.Pointer(&buf[0])),
  34. Data: ([PageSize - page.PageHdrSize]byte)(buf[page.PageHdrSize:]),
  35. },
  36. handle: handle,
  37. }, nil
  38. }
  39. // -----------------------
  40. // 修复完成!Alloc 返回 【数据区内部偏移】(去掉页头)
  41. // -----------------------
  42. //func (hp *HeapPage) Alloc(need uint32) (allocPageID uint32, allocOff uint32, err error) {
  43. // if need > PageSize-page.PageHdrSize {
  44. // return 0, 0, ErrHeapPageTooLarge
  45. // }
  46. //
  47. // // 1. 计算剩余空间(只算数据区)
  48. // usedData := hp.Info.Hdr.UseSize - page.PageHdrSize // 已用数据区大小
  49. // freeData := (PageSize - page.PageHdrSize) - usedData // 剩余数据区大小
  50. //
  51. // // 空间足够 → 分配【数据区偏移】
  52. // if freeData >= need {
  53. // // 🔥 核心修复:返回的是 Data 数组的偏移(去掉页头)
  54. // off := usedData
  55. // hp.Info.Hdr.UseSize += need
  56. // _ = hp.Save()
  57. // return hp.Info.Hdr.PageID, off, nil
  58. // }
  59. //
  60. // // 2. 空间不足 → 创建新页
  61. // newHp := NewHeapPage(hp.handle, hp.Info.Hdr.Type)
  62. //
  63. // // 维护页链
  64. // hp.Info.Hdr.NextPage = newHp.Info.Hdr.PageID
  65. // newHp.Info.Hdr.PrePage = hp.Info.Hdr.PageID
  66. // _ = hp.Save()
  67. //
  68. // // 3. 新页分配:返回【数据区偏移 0】
  69. // newOff := uint32(0)
  70. // newHp.Info.Hdr.UseSize += need
  71. // _ = newHp.Save()
  72. //
  73. // return newHp.Info.Hdr.PageID, newOff, nil
  74. //}
  75. func (hp *HeapPage) Alloc(need uint32) (allocPageID uint32, allocOff uint32, err error) {
  76. // 安全检查:申请空间不能超过单页最大容量
  77. if need > PageSize-page.PageHdrSize {
  78. return 0, 0, ErrHeapPageTooLarge
  79. }
  80. // 1. 当前页剩余空间足够 → 直接分配【页内物理偏移】
  81. free := PageSize - hp.Info.Hdr.UseSize
  82. if free >= need {
  83. // ✅ 直接返回当前页的物理偏移(包含页头,真实地址)
  84. off := hp.Info.Hdr.UseSize
  85. hp.Info.Hdr.UseSize += need
  86. _ = hp.Save()
  87. return hp.Info.Hdr.PageID, off, nil
  88. }
  89. // 2. 空间不足 → 创建新堆页
  90. newHp := NewHeapPage(hp.handle, hp.Info.Hdr.Type)
  91. // 维护页双向链
  92. hp.Info.Hdr.NextPage = newHp.Info.Hdr.PageID
  93. newHp.Info.Hdr.PrePage = hp.Info.Hdr.PageID
  94. _ = hp.Save()
  95. // 3. 新页分配:返回新页的物理偏移(PageHdrSize,真实起始地址)
  96. newOff := newHp.Info.Hdr.UseSize // = page.PageHdrSize
  97. newHp.Info.Hdr.UseSize += need
  98. _ = newHp.Save()
  99. return newHp.Info.Hdr.PageID, newOff, nil
  100. }
  101. // Save 自动保存当前堆页到磁盘
  102. func (hp *HeapPage) Save() error {
  103. buf := make([]byte, PageSize)
  104. // 写入页头
  105. *(*page.PageHdr)(unsafe.Pointer(&buf[0])) = hp.Info.Hdr
  106. // 写入数据区
  107. copy(buf[page.PageHdrSize:], hp.Info.Data[:])
  108. return hp.handle.SavePage(hp.Info.Hdr.PageID, buf)
  109. }
  110. // Get 返回 HeapInfo 的零拷贝字节切片(直接指向内部内存)
  111. func (hp *HeapPage) Get() []byte {
  112. size := unsafe.Sizeof(hp.Info)
  113. ptr := (*byte)(unsafe.Pointer(&hp.Info))
  114. return unsafe.Slice(ptr, size)
  115. }