datapage.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  1. package datapage
  2. import (
  3. "TsDB2/DB/core/page"
  4. "encoding/binary"
  5. "errors"
  6. "sync"
  7. )
  8. // PageSize 索引页大小 (避免导入 index 包造成循环依赖)
  9. const PageSize = 16384
  10. var (
  11. // errRowTooLarge 行装不下当前页, 调用方需换页/重建。
  12. // 注: "未找到"语义统一用 page.ErrNotFound, 便于上层 errors.Is 判定, 不再各自造错误值。
  13. errRowTooLarge = errors.New("row too large, need heap overflow")
  14. )
  15. // =============================================================================
  16. // 统一 DataPage — 所有需要独立数据页的索引类型共享
  17. //
  18. // 磁盘布局 (权威定义见 page.DataPageHdr):
  19. // [PageHdr(20B) + Count(4B) + Min(8B) + Max(8B)] = 40B header
  20. // [len(4B) + rowData] ... = 行数据区
  21. //
  22. // len 最高位 (0x80000000) 为软删除标志
  23. // Min/Max 存储 rowData 前 8 字节的最小/最大值 (BigEndian 比较)
  24. // =============================================================================
  25. // HdrSize 数据页头部大小 (直接复用 page 包的权威布局定义)
  26. const HdrSize = page.DataPageHdrSize
  27. // DeletedFlag 软删除标志 (长度字段最高位)
  28. const DeletedFlag uint32 = 0x80000000
  29. // DataPage 统一数据页
  30. type DataPage struct {
  31. handle page.HandleDb
  32. pageID uint32
  33. buf []byte
  34. count uint32
  35. dataEnd uint32
  36. }
  37. // ======================== 页 I/O ========================
  38. // New 创建一个新的空数据页
  39. func New(handle page.HandleDb) *DataPage {
  40. pid := handle.NewPage()
  41. buf := make([]byte, PageSize)
  42. hdr := page.HdrOf(buf)
  43. hdr.Type = page.DataIndex
  44. hdr.PageID = pid
  45. hdr.UseSize = HdrSize
  46. return &DataPage{handle: handle, pageID: pid, buf: buf, count: 0, dataEnd: HdrSize}
  47. }
  48. // Load 从磁盘加载指定页
  49. func Load(handle page.HandleDb, pageID uint32) (*DataPage, error) {
  50. buf := make([]byte, PageSize)
  51. if err := handle.ReadPage(pageID, buf); err != nil {
  52. return nil, err
  53. }
  54. hdr := page.HdrOf(buf)
  55. cnt := page.DataHdrOf(buf).Count
  56. return &DataPage{
  57. handle: handle, pageID: pageID, buf: buf,
  58. count: cnt, dataEnd: hdr.UseSize,
  59. }, nil
  60. }
  61. // Save 持久化到磁盘
  62. func (dp *DataPage) Save() {
  63. page.HdrOf(dp.buf).UseSize = dp.dataEnd
  64. page.DataHdrOf(dp.buf).Count = dp.count
  65. _ = dp.handle.SavePage(dp.pageID, dp.buf)
  66. }
  67. // PageID 返回当前页 ID
  68. func (dp *DataPage) PageID() uint32 { return dp.pageID }
  69. // Count 返回行计数
  70. func (dp *DataPage) Count() uint32 { return dp.count }
  71. // IsFull 判断是否有足够空间追加新行
  72. func (dp *DataPage) IsFull(rowSize uint32) bool {
  73. return dp.dataEnd+rowSize+4 >= uint32(len(dp.buf))
  74. }
  75. // ======================== Min/Max 维护 ========================
  76. // getMin 读取当前 Min 值
  77. func (dp *DataPage) getMin() uint64 { return page.DataHdrOf(dp.buf).GetMin() }
  78. // getMax 读取当前 Max 值
  79. func (dp *DataPage) getMax() uint64 { return page.DataHdrOf(dp.buf).GetMax() }
  80. // MinPK 返回页内最小 pkID (Min 字段的公开访问)
  81. func (dp *DataPage) MinPK() uint64 { return dp.getMin() }
  82. // MaxPK 返回页内最大 pkID (Max 字段的公开访问)
  83. func (dp *DataPage) MaxPK() uint64 { return dp.getMax() }
  84. // updateMinMax 追加行后更新 Min/Max (取 rowData 前 8 字节 BigEndian 比较)
  85. func (dp *DataPage) updateMinMax(rowData []byte) {
  86. if len(rowData) < 8 {
  87. return
  88. }
  89. val := binary.BigEndian.Uint64(rowData[:8])
  90. dh := page.DataHdrOf(dp.buf)
  91. if dp.count <= 1 {
  92. // 第一行 (或刚从 0 变 1), 直接设置
  93. dh.SetMin(val)
  94. dh.SetMax(val)
  95. return
  96. }
  97. if val < dh.GetMin() {
  98. dh.SetMin(val)
  99. }
  100. if val > dh.GetMax() {
  101. dh.SetMax(val)
  102. }
  103. }
  104. // recomputeMinMax 依据活行重算 Min/Max (取每行前 8 字节 BigEndian)
  105. func (dp *DataPage) recomputeMinMax(rows [][]byte) {
  106. var minV, maxV uint64
  107. first := true
  108. for _, r := range rows {
  109. if len(r) < 8 {
  110. continue
  111. }
  112. v := binary.BigEndian.Uint64(r[:8])
  113. if first {
  114. minV, maxV, first = v, v, false
  115. continue
  116. }
  117. if v < minV {
  118. minV = v
  119. }
  120. if v > maxV {
  121. maxV = v
  122. }
  123. }
  124. if first {
  125. minV, maxV = 0, 0
  126. }
  127. dh := page.DataHdrOf(dp.buf)
  128. dh.SetMin(minV)
  129. dh.SetMax(maxV)
  130. }
  131. // ======================== 行操作 ========================
  132. // AppendRow 追加一行
  133. // storeRow 格式: [pkID(8B LE) + rowData] 或纯 rowData, 由调用方决定
  134. func (dp *DataPage) AppendRow(storeRow []byte) {
  135. off := dp.dataEnd
  136. binary.LittleEndian.PutUint32(dp.buf[off:], uint32(len(storeRow)))
  137. off += 4
  138. copy(dp.buf[off:], storeRow)
  139. off += uint32(len(storeRow))
  140. dp.dataEnd = off
  141. dp.count++
  142. // 更新 Min/Max: 取 storeRow 前 8 字节
  143. dp.updateMinMax(storeRow)
  144. }
  145. // InsertRowSorted 保持"页内行按 pkID 升序"不变式, 把行插到正确位置。
  146. // 返回 false 表示页内空间不足, 调用方需换页。
  147. //
  148. // 为什么不能直接用 AppendRow: FindRowByPK 依赖行按 pkID 升序, 遇到比目标更大的行就
  149. // 提前判定"不存在"。主键由调用方显式给出时 (自定义主键 / BaseModel.ID) 插入顺序与
  150. // pkID 顺序无关, AppendRow 会把小 pkID 排到大 pkID 后面 → 行明明在页里, 却查不到
  151. // (全叶扫描兜底也走同一个 FindRowByPK, 同样漏)。
  152. func (dp *DataPage) InsertRowSorted(storeRow []byte) bool {
  153. return dp.InsertRowSortedByOffset(storeRow, 0)
  154. }
  155. // InsertRowSortedByOffset 按 storeRow 中 keyOff 处的 8 字节 BigEndian 键升序插入。
  156. //
  157. // 与 InsertRowSorted 的唯一区别只是"排序键在哪":
  158. // - 主键 / 二级索引的行, 键(或 pkID 前缀)在偏移 0;
  159. // - 时序行是 [pkID(8B)][schemaVer(1B)][字段...], 时间键(首列)在偏移 9。
  160. //
  161. // 两种布局都需要页内有序: 有序的页才能让查找遇到更大键就提前终止, 也让范围扫描
  162. // 能在页内直接二分/截断, 而不是整页逐行过滤。行长度不足以容纳该键时退化为追加。
  163. func (dp *DataPage) InsertRowSortedByOffset(storeRow []byte, keyOff int) bool {
  164. need := uint32(4 + len(storeRow))
  165. if dp.dataEnd+need >= uint32(len(dp.buf)) {
  166. return false
  167. }
  168. hasKey := keyOff >= 0 && len(storeRow) >= keyOff+8
  169. var key uint64
  170. if hasKey {
  171. key = binary.BigEndian.Uint64(storeRow[keyOff : keyOff+8])
  172. }
  173. // 找到第一个排序键大于 key 的行, 插在它前面; 没有则追加到末尾
  174. ins := dp.dataEnd
  175. if hasKey {
  176. off := HdrSize
  177. for i := uint32(0); i < dp.count; i++ {
  178. rowLen, _, rowStart, ok := dp.nextRow(off)
  179. if !ok {
  180. break
  181. }
  182. if rowLen >= uint32(keyOff+8) &&
  183. binary.BigEndian.Uint64(dp.buf[rowStart+uint32(keyOff):rowStart+uint32(keyOff)+8]) > key {
  184. ins = off
  185. break
  186. }
  187. off = rowStart + rowLen
  188. }
  189. }
  190. if ins < dp.dataEnd {
  191. copy(dp.buf[ins+need:dp.dataEnd+need], dp.buf[ins:dp.dataEnd])
  192. }
  193. binary.LittleEndian.PutUint32(dp.buf[ins:], uint32(len(storeRow)))
  194. copy(dp.buf[ins+4:], storeRow)
  195. dp.dataEnd += need
  196. dp.count++
  197. dp.updateMinMax(storeRow)
  198. return true
  199. }
  200. // FindRowByPK 按 pkID 查找 (pkKeyBE 为 BigEndian, 匹配 storedRow[0:8])
  201. // 优化: 行按 pkID 顺序存储, 找到 pkID > target 时提前终止
  202. //
  203. // ⚠️ 仅当页内行确实按 pkID 升序时才能用: 提前终止会把"页里明明有"的行判成不存在。
  204. // 时序 DataPage 的行按时间键排序 (见 InsertRowSortedByOffset), pkID 无序, 必须走
  205. // FindRowByPKLinear。
  206. func (dp *DataPage) FindRowByPK(pkKeyBE []byte) ([]byte, bool) {
  207. keyPK := binary.BigEndian.Uint64(pkKeyBE[:8])
  208. off := HdrSize
  209. for i := uint32(0); i < dp.count; i++ {
  210. rowLen, deleted, rowStart, ok := dp.nextRow(off)
  211. if !ok {
  212. return nil, false
  213. }
  214. off = rowStart + rowLen
  215. if deleted {
  216. continue
  217. }
  218. if rowLen >= 8 {
  219. rowPK := binary.BigEndian.Uint64(dp.buf[rowStart : rowStart+8])
  220. if rowPK == keyPK {
  221. result := make([]byte, rowLen)
  222. copy(result, dp.buf[rowStart:rowStart+rowLen])
  223. return result, true
  224. }
  225. if rowPK > keyPK {
  226. // 行按 pkID 顺序, 当前行 pkID > 目标, 后续行更大, 提前终止
  227. return nil, false
  228. }
  229. }
  230. }
  231. return nil, false
  232. }
  233. // FindRowByPKLinear 按 pkID 全页扫描查找, 不做"遇到更大行号即提前结束"的优化。
  234. // 页内行不按 pkID 有序时 (时序 DataPage 按时间键排序) 必须用本方法, 否则会漏行。
  235. func (dp *DataPage) FindRowByPKLinear(pkKeyBE []byte) ([]byte, bool) {
  236. keyPK := binary.BigEndian.Uint64(pkKeyBE[:8])
  237. off := HdrSize
  238. for i := uint32(0); i < dp.count; i++ {
  239. rowLen, deleted, rowStart, ok := dp.nextRow(off)
  240. if !ok {
  241. return nil, false
  242. }
  243. off = rowStart + rowLen
  244. if deleted || rowLen < 8 {
  245. continue
  246. }
  247. if binary.BigEndian.Uint64(dp.buf[rowStart:rowStart+8]) == keyPK {
  248. result := make([]byte, rowLen)
  249. copy(result, dp.buf[rowStart:rowStart+rowLen])
  250. return result, true
  251. }
  252. }
  253. return nil, false
  254. }
  255. // FindRowByIndexKey 按 rowData 中指定偏移处的 8 字节匹配
  256. // indexKeyBE 为 BigEndian 编码的索引键
  257. // storedOffset 为 storedRow 中比较的起始偏移
  258. func (dp *DataPage) FindRowByIndexKey(indexKeyBE []byte, storedOffset int) ([]byte, bool) {
  259. keyVal := binary.BigEndian.Uint64(indexKeyBE[:8])
  260. off := HdrSize
  261. for i := uint32(0); i < dp.count; i++ {
  262. rowLen, deleted, rowStart, ok := dp.nextRow(off)
  263. if !ok {
  264. return nil, false
  265. }
  266. off = rowStart + rowLen
  267. if deleted {
  268. continue
  269. }
  270. if int(rowLen) >= storedOffset+8 {
  271. rowVal := binary.BigEndian.Uint64(dp.buf[rowStart+uint32(storedOffset) : rowStart+uint32(storedOffset)+8])
  272. if rowVal == keyVal {
  273. result := make([]byte, rowLen)
  274. copy(result, dp.buf[rowStart:rowStart+rowLen])
  275. return result, true
  276. }
  277. }
  278. }
  279. return nil, false
  280. }
  281. // DeleteByPK 按 pkID 软删除, 返回是否找到
  282. func (dp *DataPage) DeleteByPK(pkKeyBE []byte) bool {
  283. keyPK := binary.BigEndian.Uint64(pkKeyBE[:8])
  284. off := HdrSize
  285. for i := uint32(0); i < dp.count; i++ {
  286. rowLen, deleted, rowStart, ok := dp.nextRow(off)
  287. if !ok {
  288. return false
  289. }
  290. lenOff := off
  291. off = rowStart + rowLen
  292. if deleted {
  293. continue
  294. }
  295. if rowLen >= 8 {
  296. rowPK := binary.BigEndian.Uint64(dp.buf[rowStart : rowStart+8])
  297. if rowPK == keyPK {
  298. binary.LittleEndian.PutUint32(dp.buf[lenOff:], rowLen|DeletedFlag)
  299. return true
  300. }
  301. }
  302. }
  303. return false
  304. }
  305. // DeleteByIndexKey 按 rowData 中指定偏移处的 8 字节匹配并软删除
  306. func (dp *DataPage) DeleteByIndexKey(indexKeyBE []byte, storedOffset int) bool {
  307. keyVal := binary.BigEndian.Uint64(indexKeyBE[:8])
  308. off := HdrSize
  309. for i := uint32(0); i < dp.count; i++ {
  310. rowLen, deleted, rowStart, ok := dp.nextRow(off)
  311. if !ok {
  312. return false
  313. }
  314. lenOff := off
  315. off = rowStart + rowLen
  316. if deleted {
  317. continue
  318. }
  319. if int(rowLen) >= storedOffset+8 {
  320. rowVal := binary.BigEndian.Uint64(dp.buf[rowStart+uint32(storedOffset) : rowStart+uint32(storedOffset)+8])
  321. if rowVal == keyVal {
  322. binary.LittleEndian.PutUint32(dp.buf[lenOff:], rowLen|DeletedFlag)
  323. return true
  324. }
  325. }
  326. }
  327. return false
  328. }
  329. // UpdateByPK 按 pkID 原地更新行数据 (newStoreRow 格式同 AppendRow)
  330. func (dp *DataPage) UpdateByPK(pkKeyBE []byte, newStoreRow []byte) error {
  331. keyPK := binary.BigEndian.Uint64(pkKeyBE[:8])
  332. off := HdrSize
  333. for i := uint32(0); i < dp.count; i++ {
  334. rowLen, deleted, rowStart, ok := dp.nextRow(off)
  335. if !ok {
  336. break
  337. }
  338. off = rowStart + rowLen
  339. if deleted {
  340. continue
  341. }
  342. if rowLen >= 8 {
  343. rowPK := binary.BigEndian.Uint64(dp.buf[rowStart : rowStart+8])
  344. if rowPK == keyPK {
  345. if uint32(len(newStoreRow)) <= rowLen {
  346. copy(dp.buf[rowStart:], newStoreRow)
  347. for j := uint32(len(newStoreRow)); j < rowLen; j++ {
  348. dp.buf[rowStart+j] = 0
  349. }
  350. dp.Save()
  351. return nil
  352. }
  353. return errRowTooLarge
  354. }
  355. }
  356. }
  357. return page.ErrNotFound
  358. }
  359. // FindAndUpdateByIndexKey 按 rowData 偏移匹配找到行后, 用 newStoreRow 原地更新
  360. func (dp *DataPage) FindAndUpdateByIndexKey(indexKeyBE []byte, storedOffset int, newStoreRow []byte) error {
  361. keyVal := binary.BigEndian.Uint64(indexKeyBE[:8])
  362. off := HdrSize
  363. for i := uint32(0); i < dp.count; i++ {
  364. rowLen, deleted, rowStart, ok := dp.nextRow(off)
  365. if !ok {
  366. break
  367. }
  368. off = rowStart + rowLen
  369. if deleted {
  370. continue
  371. }
  372. if int(rowLen) >= storedOffset+8 {
  373. rowVal := binary.BigEndian.Uint64(dp.buf[rowStart+uint32(storedOffset) : rowStart+uint32(storedOffset)+8])
  374. if rowVal == keyVal {
  375. if uint32(len(newStoreRow)) <= rowLen {
  376. copy(dp.buf[rowStart:], newStoreRow)
  377. for j := uint32(len(newStoreRow)); j < rowLen; j++ {
  378. dp.buf[rowStart+j] = 0
  379. }
  380. dp.Save()
  381. return nil
  382. }
  383. return errRowTooLarge
  384. }
  385. }
  386. }
  387. return page.ErrNotFound
  388. }
  389. // RebuildWith 页内重建 (repack): 保持活行原有顺序紧凑重排, 并把 pkKeyBE 对应的行
  390. // 原地替换为 newStoreRow, 允许该行**变长**。
  391. //
  392. // 用途: schema 演进 (AddField) 后旧行的 schemaVer 与行长都会变化, UpdateByPK 因
  393. // "新行长 > 旧行长" 返回 errRowTooLarge 时, 用本方法在页内腾挪:
  394. // - 顺带回收墓碑 (已删除行) 占用的碎片空间
  395. // - 只要整页还装得下, 变长行无需换页
  396. //
  397. // 安全性: 行以自描述的 4B 长度前缀顺序排列, 页内偏移不对外暴露 (外部只通过
  398. // B+ 树叶子的 dpID 定位页面后顺序扫描), 因此页内重排不会破坏任何索引。
  399. //
  400. // 返回 page.ErrNotFound 表示目标行不在本页; 返回 errRowTooLarge 表示整页装不下, 调用方需换页。
  401. func (dp *DataPage) RebuildWith(pkKeyBE []byte, newStoreRow []byte) error {
  402. return dp.RebuildWithIndexKey(pkKeyBE, 0, newStoreRow)
  403. }
  404. // RebuildWithIndexKey 同 RebuildWith, 但按 storedRow 中 storedOffset 处的 8 字节匹配
  405. // (副索引/时序行布局: 见 FindAndUpdateByIndexKey)
  406. func (dp *DataPage) RebuildWithIndexKey(indexKeyBE []byte, storedOffset int, newStoreRow []byte) error {
  407. if len(indexKeyBE) < 8 {
  408. return page.ErrNotFound
  409. }
  410. keyVal := binary.BigEndian.Uint64(indexKeyBE[:8])
  411. // 1. 收集活行, 命中目标键的位置替换为新行
  412. live := make([][]byte, 0, dp.count)
  413. off := HdrSize
  414. replaced := false
  415. for i := uint32(0); i < dp.count; i++ {
  416. rowLen, deleted, rowStart, ok := dp.nextRow(off)
  417. if !ok {
  418. break
  419. }
  420. off = rowStart + rowLen
  421. if deleted {
  422. continue
  423. }
  424. if !replaced && int(rowLen) >= storedOffset+8 &&
  425. binary.BigEndian.Uint64(dp.buf[rowStart+uint32(storedOffset):rowStart+uint32(storedOffset)+8]) == keyVal {
  426. replaced = true
  427. live = append(live, newStoreRow)
  428. continue
  429. }
  430. row := make([]byte, rowLen)
  431. copy(row, dp.buf[rowStart:rowStart+rowLen])
  432. live = append(live, row)
  433. }
  434. if !replaced {
  435. return page.ErrNotFound
  436. }
  437. // 2. 预计算总占用, 装不下则告知调用方换页
  438. const rowHdrSize = uint32(4) // 每行 4B 长度前缀
  439. total := HdrSize
  440. for _, r := range live {
  441. total += rowHdrSize + uint32(len(r))
  442. }
  443. if total > uint32(len(dp.buf)) {
  444. return errRowTooLarge
  445. }
  446. // 3. 按原顺序紧凑重写
  447. w := HdrSize
  448. for _, r := range live {
  449. binary.LittleEndian.PutUint32(dp.buf[w:], uint32(len(r)))
  450. w += rowHdrSize
  451. copy(dp.buf[w:], r)
  452. w += uint32(len(r))
  453. }
  454. for i := w; i < dp.dataEnd; i++ {
  455. dp.buf[i] = 0
  456. }
  457. dp.dataEnd = w
  458. dp.count = uint32(len(live))
  459. dp.recomputeMinMax(live)
  460. dp.Save()
  461. return nil
  462. }
  463. // AllDeleted 检查是否所有行都已删除
  464. func (dp *DataPage) AllDeleted() bool {
  465. off := HdrSize
  466. for i := uint32(0); i < dp.count; i++ {
  467. rowLen, deleted, rowStart, ok := dp.nextRow(off)
  468. if !ok {
  469. return true
  470. }
  471. if !deleted {
  472. return false
  473. }
  474. off = rowStart + rowLen
  475. }
  476. return true
  477. }
  478. // GetAllRows 返回所有未删除的行
  479. func (dp *DataPage) GetAllRows() [][]byte {
  480. var result [][]byte
  481. off := HdrSize
  482. for i := uint32(0); i < dp.count; i++ {
  483. rowLen, deleted, rowStart, ok := dp.nextRow(off)
  484. if !ok {
  485. break
  486. }
  487. off = rowStart + rowLen
  488. if deleted {
  489. continue
  490. }
  491. row := make([]byte, rowLen)
  492. copy(row, dp.buf[rowStart:rowStart+rowLen])
  493. result = append(result, row)
  494. }
  495. return result
  496. }
  497. // GetAllRowsPooled 同 GetAllRows, 但从 sync.Pool 获取缓冲区
  498. // 调用方处理完后必须将每个 []byte 归还给 pool
  499. func (dp *DataPage) GetAllRowsPooled(pool *sync.Pool) [][]byte {
  500. var result [][]byte
  501. off := HdrSize
  502. for i := uint32(0); i < dp.count; i++ {
  503. rowLen, deleted, rowStart, ok := dp.nextRow(off)
  504. if !ok {
  505. break
  506. }
  507. off = rowStart + rowLen
  508. if deleted {
  509. continue
  510. }
  511. // 从池中获取缓冲区, 避免 make 分配
  512. bp := pool.Get().(*[]byte)
  513. buf := *bp
  514. copy(buf[:rowLen], dp.buf[rowStart:rowStart+rowLen])
  515. result = append(result, buf[:rowLen])
  516. }
  517. return result
  518. }
  519. // GetAllRowsReversed 返回所有未删除行,顺序反转(最后一行在前)
  520. func (dp *DataPage) GetAllRowsReversed() [][]byte {
  521. rows := dp.GetAllRows()
  522. for i, j := 0, len(rows)-1; i < j; i, j = i+1, j-1 {
  523. rows[i], rows[j] = rows[j], rows[i]
  524. }
  525. return rows
  526. }
  527. // RewriteRows 用给定行紧凑重写整页 (顺带回收墓碑), 行顺序即入参顺序。
  528. //
  529. // 页分裂 / 页内重排都靠它: 一次写入即完成 "丢弃墓碑 + 重排 + 重算 Count/Min/Max"。
  530. // 返回 false 表示总占用超出页容量 (调用方需换页或分裂), 此时页内容保持不变。
  531. func (dp *DataPage) RewriteRows(rows [][]byte) bool {
  532. const rowHdr = uint32(4) // 每行 4B 长度前缀
  533. total := HdrSize
  534. for _, r := range rows {
  535. total += rowHdr + uint32(len(r))
  536. }
  537. if total > uint32(len(dp.buf)) {
  538. return false
  539. }
  540. w := HdrSize
  541. for _, r := range rows {
  542. binary.LittleEndian.PutUint32(dp.buf[w:], uint32(len(r)))
  543. w += rowHdr
  544. copy(dp.buf[w:], r)
  545. w += uint32(len(r))
  546. }
  547. for i := w; i < dp.dataEnd; i++ {
  548. dp.buf[i] = 0
  549. }
  550. dp.dataEnd = w
  551. dp.count = uint32(len(rows))
  552. dp.recomputeMinMax(rows)
  553. return true
  554. }
  555. // AppendRows 依次追加多行: 先整体校验容量, 再逐行写入。
  556. // 任一行装不下时整页保持原样并返回 false —— 不会留下"写了一半"的页。
  557. func (dp *DataPage) AppendRows(rows [][]byte) bool {
  558. total := dp.dataEnd
  559. for _, r := range rows {
  560. total += 4 + uint32(len(r))
  561. }
  562. if total > uint32(len(dp.buf)) {
  563. return false
  564. }
  565. for _, r := range rows {
  566. dp.AppendRow(r)
  567. }
  568. return true
  569. }
  570. // ======================== 内部辅助 ========================
  571. // nextRow 解析下一行: 返回 (数据长度, 是否已删除, 数据起始偏移, 是否有效)
  572. func (dp *DataPage) nextRow(off uint32) (rowLen uint32, deleted bool, rowStart uint32, ok bool) {
  573. if off+4 > dp.dataEnd {
  574. return 0, false, 0, false
  575. }
  576. rawLen := binary.LittleEndian.Uint32(dp.buf[off:])
  577. deleted = rawLen&DeletedFlag != 0
  578. rowLen = rawLen & ^DeletedFlag
  579. rowStart = off + 4
  580. if rowStart+rowLen > dp.dataEnd {
  581. return 0, false, 0, false
  582. }
  583. return rowLen, deleted, rowStart, true
  584. }
  585. // ======================== IDateEntry 接口实现 ========================
  586. // 供时序索引等扁平链模式使用
  587. // IDateEntryDataPage 包装 DataPage 使其实现 IDateEntry 接口
  588. // FindDataPage 回调负责从 indexEntries 中找到目标 DataPageID
  589. type IDateEntryDataPage struct {
  590. FindDataPage func(indexEntries []byte, entryLen int, count int, key []byte) uint32
  591. }
  592. func (d *IDateEntryDataPage) Insert(handle page.HandleDb, indexEntries []byte, entryLen int, count int, key []byte, pkID uint64, rowData []byte) error {
  593. dpID := d.FindDataPage(indexEntries, entryLen, count, key)
  594. var dp *DataPage
  595. if dpID == 0 {
  596. dp = New(handle)
  597. } else {
  598. var err error
  599. dp, err = Load(handle, dpID)
  600. if err != nil {
  601. return err
  602. }
  603. }
  604. if dp.IsFull(uint32(8 + len(rowData))) {
  605. dp.Save()
  606. dp = New(handle)
  607. }
  608. storeRow := make([]byte, 8+len(rowData))
  609. binary.BigEndian.PutUint64(storeRow[:8], pkID)
  610. copy(storeRow[8:], rowData)
  611. dp.AppendRow(storeRow)
  612. dp.Save()
  613. return nil
  614. }
  615. func (d *IDateEntryDataPage) Search(handle page.HandleDb, indexEntries []byte, entryLen int, key []byte) ([]byte, bool) {
  616. n := len(indexEntries) / entryLen
  617. dpID := d.FindDataPage(indexEntries, entryLen, n, key)
  618. if dpID == 0 {
  619. return nil, false
  620. }
  621. dp, err := Load(handle, dpID)
  622. if err != nil {
  623. return nil, false
  624. }
  625. // 时序行布局: [pkID(8)][schemaVer(1)][字段...], 时间戳是首列 → storedRow 偏移 9
  626. return dp.FindRowByIndexKey(key, 9)
  627. }
  628. func (d *IDateEntryDataPage) Update(handle page.HandleDb, indexEntries []byte, entryLen int, key []byte, pkID uint64, rowData []byte) error {
  629. n := len(indexEntries) / entryLen
  630. dpID := d.FindDataPage(indexEntries, entryLen, n, key)
  631. if dpID == 0 {
  632. return page.ErrNotFound
  633. }
  634. dp, err := Load(handle, dpID)
  635. if err != nil {
  636. return err
  637. }
  638. storeRow := make([]byte, 8+len(rowData))
  639. binary.BigEndian.PutUint64(storeRow[:8], pkID)
  640. copy(storeRow[8:], rowData)
  641. return dp.FindAndUpdateByIndexKey(key, 9, storeRow)
  642. }
  643. func (d *IDateEntryDataPage) Delete(handle page.HandleDb, indexEntries []byte, entryLen int, key []byte) error {
  644. n := len(indexEntries) / entryLen
  645. dpID := d.FindDataPage(indexEntries, entryLen, n, key)
  646. if dpID == 0 {
  647. return page.ErrNotFound
  648. }
  649. dp, err := Load(handle, dpID)
  650. if err != nil {
  651. return err
  652. }
  653. deleted := dp.DeleteByIndexKey(key, 9)
  654. if !deleted {
  655. return page.ErrNotFound
  656. }
  657. if dp.AllDeleted() {
  658. if handle.FreePage != nil {
  659. handle.FreePage(dp.pageID)
  660. }
  661. } else {
  662. dp.Save()
  663. }
  664. return nil
  665. }
  666. func (d *IDateEntryDataPage) CreateDataPage(handle page.HandleDb, key []byte, pkID uint64, rowData []byte) (uint32, error) {
  667. dp := New(handle)
  668. storeRow := make([]byte, 8+len(rowData))
  669. binary.BigEndian.PutUint64(storeRow[:8], pkID)
  670. copy(storeRow[8:], rowData)
  671. dp.AppendRow(storeRow)
  672. dp.Save()
  673. return dp.pageID, nil
  674. }