datapage.go 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. package page
  2. import (
  3. "encoding/binary"
  4. "unsafe"
  5. )
  6. // =============================================================================
  7. // DataPageHdr —— 数据页头: 公共页头 + 行计数 + pkID 极值。
  8. //
  9. // 磁盘布局 (40B):
  10. //
  11. // off 0 PageHdr 20B 公共页头
  12. // off 20 Count 4B 行数 (本机字节序)
  13. // off 24 Min 8B 页内最小 pkID ★BigEndian 编码★
  14. // off 32 Max 8B 页内最大 pkID ★BigEndian 编码★
  15. //
  16. // 行数据区紧接在偏移 40 之后, 每行 [len(4B)][rowData...], len 的最高位是软删除标志。
  17. //
  18. // ⚠️ Min/Max 刻意按 BigEndian 存放 (pkID 本身也按 BE 比较), 所以这里声明成
  19. // [8]byte 而不是 uint64 —— 若声明成 uint64, unsafe 映射在小端机上会读到字节反转
  20. // 的值。读写必须走 GetMin/SetMin/GetMax/SetMax。
  21. //
  22. // 这份布局原先在 wal.go(dpHdrSize/dpCountOffset/dpUseSizeOffset)、transaction.go、
  23. // index/datapage 三处各写一遍, 现在只有这里一处定义。
  24. // =============================================================================
  25. type DataPageHdr struct {
  26. PageHdr
  27. Count uint32 // off 20 行数
  28. Min [8]byte // off 24 最小 pkID (BigEndian)
  29. Max [8]byte // off 32 最大 pkID (BigEndian)
  30. }
  31. // DataPageHdrSize 数据页头长度; 行数据区从该偏移开始
  32. const DataPageHdrSize = uint32(unsafe.Sizeof(DataPageHdr{})) // 40
  33. // 编译期布局断言
  34. var (
  35. _ [40]byte = [unsafe.Sizeof(DataPageHdr{})]byte{} // 头必须 40 字节
  36. _ [20]byte = [unsafe.Offsetof(DataPageHdr{}.Count)]byte{} // Count 必须偏移 20
  37. _ [24]byte = [unsafe.Offsetof(DataPageHdr{}.Min)]byte{} // Min 必须偏移 24
  38. _ [32]byte = [unsafe.Offsetof(DataPageHdr{}.Max)]byte{} // Max 必须偏移 32
  39. )
  40. // DataHdrOf 把页缓冲区按 DataPageHdr 解析 (页头固定在偏移 0)。
  41. func DataHdrOf(buf []byte) *DataPageHdr {
  42. return (*DataPageHdr)(unsafe.Pointer(&buf[0]))
  43. }
  44. // GetMin 读页内最小 pkID。
  45. func (h *DataPageHdr) GetMin() uint64 { return binary.BigEndian.Uint64(h.Min[:]) }
  46. // SetMin 写页内最小 pkID。
  47. func (h *DataPageHdr) SetMin(v uint64) { binary.BigEndian.PutUint64(h.Min[:], v) }
  48. // GetMax 读页内最大 pkID。
  49. func (h *DataPageHdr) GetMax() uint64 { return binary.BigEndian.Uint64(h.Max[:]) }
  50. // SetMax 写页内最大 pkID。
  51. func (h *DataPageHdr) SetMax(v uint64) { binary.BigEndian.PutUint64(h.Max[:], v) }