primary.go 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253
  1. package btree
  2. import (
  3. "TsDB2/DB/core/index/datapage"
  4. "TsDB2/DB/core/page"
  5. "encoding/binary"
  6. "errors"
  7. "fmt"
  8. "unsafe"
  9. )
  10. // btNode B+ 鏍戣妭鐐?(raw bytes + page.IndexHead 鎸囬拡, 鏃?IndexPage 瀵硅薄)
  11. type btNode struct {
  12. buf []byte // 瀹屾暣椤电紦鍐插尯
  13. info *page.IndexHead // 鎸囧悜 buf 澶撮儴鐨?page.IndexHead 鎸囬拡
  14. entries []byte // buf[page.IndexHeadSize:] 鏉$洰鍖哄煙
  15. }
  16. func (n *btNode) isLeaf() bool { return n.info.IsLeaf == 1 }
  17. func (n *btNode) pageID() uint32 { return n.info.Hdr.PageID }
  18. // btPathEntry 璁板綍 B+ 鏍?descent 璺緞
  19. type btPathEntry struct {
  20. nodePID uint32
  21. childIdx int
  22. }
  23. // btSplitThreshold 璁$畻鍒嗚闃堝€?
  24. func btSplitThreshold() int {
  25. ff := page.BTreeFillFactor
  26. if ff < 50 {
  27. ff = 50
  28. }
  29. if ff > 100 {
  30. ff = 100
  31. }
  32. return int(page.IndexPageSize) * ff / 100
  33. }
  34. // ======================== 鑺傜偣 I/O ========================
  35. func btLoad(handle page.HandleDb, pid uint32) *btNode {
  36. if pid == 0 {
  37. return nil
  38. }
  39. buf := make([]byte, page.IndexPageSize)
  40. if err := handle.ReadPage(pid, buf); err != nil {
  41. return nil
  42. }
  43. info := (*page.IndexHead)(unsafe.Pointer(&buf[0]))
  44. return &btNode{buf: buf, info: info, entries: buf[page.IndexHeadSize:]}
  45. }
  46. func btSave(handle page.HandleDb, n *btNode) {
  47. _ = handle.SavePage(n.info.Hdr.PageID, n.buf)
  48. }
  49. func btNew(handle page.HandleDb, isLeaf bool, entryLen int) *btNode {
  50. pid := handle.NewPage()
  51. buf := make([]byte, page.IndexPageSize)
  52. info := (*page.IndexHead)(unsafe.Pointer(&buf[0]))
  53. info.Hdr.Type = page.IndexDataIndex
  54. info.Hdr.PageID = pid
  55. info.Hdr.UseSize = uint32(page.IndexHeadSize)
  56. info.IndexType = page.IndexTypePrimary
  57. info.EntryLen = uint16(entryLen)
  58. info.Count = 0
  59. if isLeaf {
  60. info.IsLeaf = 1
  61. }
  62. return &btNode{buf: buf, info: info, entries: buf[page.IndexHeadSize:]}
  63. }
  64. // ======================== 鏉$洰鎿嶄綔 ========================
  65. func btEntry(n *btNode, i int) []byte {
  66. el := int(n.info.EntryLen)
  67. return n.entries[i*el : (i+1)*el]
  68. }
  69. func btKey(e []byte) []byte { return e[:len(e)-4] }
  70. func btPID(e []byte) uint32 { return binary.BigEndian.Uint32(e[len(e)-4:]) }
  71. func btSetPID(e []byte, p uint32) { binary.BigEndian.PutUint32(e[len(e)-4:], p) }
  72. func btCmp(a, b []byte) int {
  73. ml := len(a)
  74. if len(b) < ml {
  75. ml = len(b)
  76. }
  77. for i := 0; i < ml; i++ {
  78. if a[i] < b[i] {
  79. return -1
  80. }
  81. if a[i] > b[i] {
  82. return 1
  83. }
  84. }
  85. if len(a) < len(b) {
  86. return -1
  87. }
  88. if len(a) > len(b) {
  89. return 1
  90. }
  91. return 0
  92. }
  93. func btRoute(n *btNode, key []byte) uint32 {
  94. cnt := int(n.info.Count)
  95. // 二分查找: 找最后一个 entry.key <= key 的位置 (与二级 B+ 树统一 <= 约定)
  96. left, right := 0, cnt-1
  97. result := 0
  98. for left <= right {
  99. mid := (left + right) / 2
  100. if btCmp(btKey(btEntry(n, mid)), key) <= 0 {
  101. result = mid
  102. left = mid + 1 // 继续向右找
  103. } else {
  104. right = mid - 1
  105. }
  106. }
  107. return btPID(btEntry(n, result))
  108. }
  109. // maxLeafEntries 单个叶节点最大条目数
  110. func maxLeafEntries(entryLen int) int {
  111. threshold := btSplitThreshold()
  112. available := threshold - page.IndexHeadSize
  113. if available <= 0 {
  114. return 1
  115. }
  116. return available / entryLen
  117. }
  118. // BuildFromSorted 从已排序的叶条目批量构建 B+ 树 (自底向上)
  119. // leafEntries: 每个条目 = [key(8B) + dpID(4B BE)], 已按 key 升序排列
  120. // 返回新树根 pageID
  121. //
  122. // 内存优化: 避免逐行 B+ 树搜索 (每次 btLoad 16KB), 改为顺序创建所有节点
  123. func BuildFromSorted(leafEntries [][]byte, handle page.HandleDb) uint32 {
  124. if len(leafEntries) == 0 {
  125. return 0
  126. }
  127. el := 12 // entry len: 8 key + 4 pid
  128. maxPerLeaf := maxLeafEntries(el)
  129. // ---- 构建叶节点层 ----
  130. type childInfo struct {
  131. pid uint32
  132. firstKey []byte // 该子树第一个 key (用于 > 路由)
  133. }
  134. var children []childInfo
  135. var prevLeafPID uint32
  136. // 将条目分组到叶节点 (带链表链接)
  137. for i := 0; i < len(leafEntries); {
  138. end := i + maxPerLeaf
  139. if end > len(leafEntries) {
  140. end = len(leafEntries)
  141. }
  142. leaf := btNew(handle, true, el)
  143. for j := i; j < end; j++ {
  144. src := leafEntries[j]
  145. dst := btEntry(leaf, int(leaf.info.Count))
  146. copy(dst, src)
  147. leaf.info.Count++
  148. leaf.info.Hdr.UseSize += uint32(el)
  149. }
  150. // 设置叶节点链表链接
  151. leaf.info.Hdr.PrePage = prevLeafPID
  152. if prevLeafPID != 0 {
  153. // 更新前一个叶节点的 NextPage
  154. // 注意: 前一个叶节点已经保存, 需要重新加载并更新
  155. // 但我们可以在保存前就设置好 NextPage
  156. }
  157. btSave(handle, leaf)
  158. // 更新前一个叶节点的 NextPage 指向当前叶
  159. if prevLeafPID != 0 {
  160. prevLeaf := btLoad(handle, prevLeafPID)
  161. if prevLeaf != nil {
  162. prevLeaf.info.Hdr.NextPage = leaf.pageID()
  163. btSave(handle, prevLeaf)
  164. }
  165. }
  166. prevLeafPID = leaf.pageID()
  167. children = append(children, childInfo{
  168. pid: leaf.pageID(),
  169. firstKey: leafEntries[i][:8],
  170. })
  171. i = end
  172. }
  173. if len(children) == 1 {
  174. return children[0].pid
  175. }
  176. // ---- 自底向上构建内部节点 ----
  177. // 路由约定 (btRoute): 找最后一个 entry.key <= searchKey
  178. // 内部节点条目: entry[i] = (child[i].firstKey, child[i].pid)
  179. // 即 entry[i].key = 该子树最左叶的第一个 key
  180. intEl := 12
  181. maxPerInt := maxLeafEntries(intEl)
  182. for len(children) > 1 {
  183. var parents []childInfo
  184. for i := 0; i < len(children); {
  185. end := i + maxPerInt
  186. if end > len(children) {
  187. end = len(children)
  188. }
  189. node := btNew(handle, false, intEl)
  190. for j := i; j < end; j++ {
  191. e := make([]byte, intEl)
  192. // 分隔键 = 该 child 的第一个 key
  193. copy(e[:intEl-4], children[j].firstKey)
  194. btSetPID(e, children[j].pid)
  195. dst := btEntry(node, int(node.info.Count))
  196. copy(dst, e)
  197. node.info.Count++
  198. node.info.Hdr.UseSize += uint32(intEl)
  199. }
  200. btSave(handle, node)
  201. parents = append(parents, childInfo{
  202. pid: node.pageID(),
  203. firstKey: children[i].firstKey,
  204. })
  205. i = end
  206. }
  207. children = parents
  208. }
  209. return children[0].pid
  210. }
  211. func btChildIdx(n *btNode, key []byte) int {
  212. el := int(n.info.EntryLen)
  213. cnt := int(n.info.Count)
  214. // 二分查找: 找最后一个 entry.key <= key 的位置 (与二级 B+ 树统一 <= 约定)
  215. left, right := 0, cnt-1
  216. result := 0
  217. for left <= right {
  218. mid := (left + right) / 2
  219. if btCmp(btEntry(n, mid)[:el-4], key) <= 0 {
  220. result = mid
  221. left = mid + 1 // 继续向右找
  222. } else {
  223. right = mid - 1
  224. }
  225. }
  226. return result
  227. }
  228. func btInsEntry(n *btNode, entry []byte, pos int) {
  229. el := int(n.info.EntryLen)
  230. cnt := int(n.info.Count)
  231. for i := cnt; i > pos; i-- {
  232. copy(btEntry(n, i), btEntry(n, i-1))
  233. }
  234. copy(btEntry(n, pos), entry)
  235. n.info.Count++
  236. n.info.Hdr.UseSize += uint32(el)
  237. }
  238. func btRmEntry(n *btNode, pos int) {
  239. el := int(n.info.EntryLen)
  240. cnt := int(n.info.Count)
  241. for i := pos; i < cnt-1; i++ {
  242. copy(btEntry(n, i), btEntry(n, i+1))
  243. }
  244. n.info.Count--
  245. n.info.Hdr.UseSize -= uint32(el)
  246. }
  247. func btLeafFind(n *btNode, key []byte) (int, bool) {
  248. el := int(n.info.EntryLen)
  249. cnt := int(n.info.Count)
  250. for i := 0; i < cnt; i++ {
  251. if btCmp(btEntry(n, i)[:el-4], key) == 0 {
  252. return i, true
  253. }
  254. }
  255. return 0, false
  256. }
  257. func btLeafPos(n *btNode, key []byte) int {
  258. el := int(n.info.EntryLen)
  259. cnt := int(n.info.Count)
  260. for i := 0; i < cnt; i++ {
  261. if btCmp(btEntry(n, i)[:el-4], key) >= 0 {
  262. return i
  263. }
  264. }
  265. return cnt
  266. }
  267. // btLeftmostKey 获取子树最左叶的第一个 key(用于 promoKey)
  268. func btLeftmostKey(handle page.HandleDb, nodePID uint32) []byte {
  269. cur := nodePID
  270. for {
  271. n := btLoad(handle, cur)
  272. if n == nil {
  273. return nil
  274. }
  275. if n.isLeaf() {
  276. if n.info.Count == 0 {
  277. return nil
  278. }
  279. e := btEntry(n, 0)
  280. key := make([]byte, len(btKey(e)))
  281. copy(key, btKey(e))
  282. return key
  283. }
  284. // 非叶节点,继续向左下遍历
  285. cur = btPID(btEntry(n, 0))
  286. }
  287. }
  288. // ======================== B+ 鏍戞悳绱?========================
  289. func BTreePKSearch(rootPID uint32, key []byte, handle page.HandleDb) (uint32, bool) {
  290. if rootPID == 0 {
  291. return 0, false
  292. }
  293. cur := rootPID
  294. for {
  295. n := btLoad(handle, cur)
  296. if n == nil {
  297. return 0, false
  298. }
  299. if n.isLeaf() {
  300. pos, ok := btLeafFind(n, key)
  301. if !ok {
  302. return 0, false
  303. }
  304. return btPID(btEntry(n, pos)), true
  305. }
  306. cur = btRoute(n, key)
  307. }
  308. }
  309. // ======================== B+ 鏍戝彾瀛愯妭鐐瑰畾浣?========================
  310. // BTreeFindLeftmostLeaf 浠庢牴鑺傜偣璺敱鍒版渶宸﹀彾鑺傜偣锛岃繑鍥炲彾鑺傜偣 pageID
  311. func BTreeFindLeftmostLeaf(rootPID uint32, handle page.HandleDb) uint32 {
  312. cur := rootPID
  313. for {
  314. n := btLoad(handle, cur)
  315. if n == nil {
  316. return 0
  317. }
  318. if n.isLeaf() {
  319. return n.info.Hdr.PageID
  320. }
  321. cur = btPID(btEntry(n, 0))
  322. }
  323. }
  324. // BTreeFindRightmostLeaf 浠庢牴鑺傜偣璺敱鍒版渶鍙冲彾鑺傜偣锛岃繑鍥炲彾鑺傜偣 pageID
  325. func BTreeFindRightmostLeaf(rootPID uint32, handle page.HandleDb) uint32 {
  326. cur := rootPID
  327. for {
  328. n := btLoad(handle, cur)
  329. if n == nil {
  330. return 0
  331. }
  332. if n.isLeaf() {
  333. return n.info.Hdr.PageID
  334. }
  335. cur = btPID(btEntry(n, int(n.info.Count)-1))
  336. }
  337. }
  338. // ======================== B+ 鏍戣寖鍥存壂鎻?========================
  339. // BTreePKRangeScan 涓婚敭 B+ 鏍戣寖鍥存壂鎻?
  340. func BTreePKRangeScan(rootPID uint32, handle page.HandleDb,
  341. startKey, endKey []byte, startInc, endInc bool, reverse bool,
  342. callback func(row []byte) bool) error {
  343. if rootPID == 0 {
  344. return nil
  345. }
  346. if !reverse {
  347. // 正向: 路由到 startKey 所在叶, 沿 NextPage 遍历
  348. cur := rootPID
  349. for {
  350. n := btLoad(handle, cur)
  351. if n == nil {
  352. return nil
  353. }
  354. if n.isLeaf() {
  355. break
  356. }
  357. cur = btRoute(n, startKey)
  358. }
  359. for cur != 0 {
  360. n := btLoad(handle, cur)
  361. if n == nil {
  362. break
  363. }
  364. for i := 0; i < int(n.info.Count); i++ {
  365. entry := btEntry(n, i)
  366. key := btKey(entry)
  367. if endKey != nil {
  368. cmp := btCmp(key, endKey)
  369. if cmp > 0 || (cmp == 0 && !endInc) {
  370. return nil
  371. }
  372. }
  373. if startKey != nil {
  374. cmp := btCmp(key, startKey)
  375. if cmp < 0 || (cmp == 0 && !startInc) {
  376. continue
  377. }
  378. }
  379. dpID := btPID(entry)
  380. dp, err := datapage.Load(handle, dpID)
  381. if err != nil {
  382. continue
  383. }
  384. // 每个 B+ 树条目精确匹配一行 (FindRowByIndexKey 按索引键过滤)
  385. if row, ok := dp.FindRowByIndexKey(key, 9); ok {
  386. if !callback(row) {
  387. return nil
  388. }
  389. }
  390. }
  391. cur = n.info.Hdr.NextPage
  392. }
  393. } else {
  394. // 反向: 路由到 endKey 所在叶(或最右叶), 沿 PrePage 遍历
  395. cur := rootPID
  396. if endKey != nil {
  397. for {
  398. n := btLoad(handle, cur)
  399. if n == nil {
  400. return nil
  401. }
  402. if n.isLeaf() {
  403. break
  404. }
  405. cur = btRoute(n, endKey)
  406. }
  407. } else {
  408. cur = BTreeFindRightmostLeaf(rootPID, handle)
  409. }
  410. for cur != 0 {
  411. n := btLoad(handle, cur)
  412. if n == nil {
  413. break
  414. }
  415. for i := int(n.info.Count) - 1; i >= 0; i-- {
  416. entry := btEntry(n, i)
  417. key := btKey(entry)
  418. if startKey != nil {
  419. cmp := btCmp(key, startKey)
  420. if cmp < 0 || (cmp == 0 && !startInc) {
  421. return nil
  422. }
  423. }
  424. if endKey != nil {
  425. cmp := btCmp(key, endKey)
  426. if cmp > 0 || (cmp == 0 && !endInc) {
  427. continue
  428. }
  429. }
  430. dpID := btPID(entry)
  431. dp, err := datapage.Load(handle, dpID)
  432. if err != nil {
  433. continue
  434. }
  435. if row, ok := dp.FindRowByIndexKey(key, 9); ok {
  436. if !callback(row) {
  437. return nil
  438. }
  439. }
  440. }
  441. cur = n.info.Hdr.PrePage
  442. }
  443. }
  444. return nil
  445. }
  446. // ======================== B+ 鏍戞彃鍏?========================
  447. func BTreePKInsert(rootPID uint32, key []byte, dpID uint32, handle page.HandleDb) (uint32, uint32, bool, error) {
  448. if rootPID == 0 {
  449. el := 12
  450. leaf := btNew(handle, true, el)
  451. e := make([]byte, el)
  452. copy(e[:8], key)
  453. btSetPID(e, dpID)
  454. btInsEntry(leaf, e, 0)
  455. btSave(handle, leaf)
  456. return leaf.pageID(), 0, false, nil
  457. }
  458. var path []btPathEntry
  459. cur := rootPID
  460. for {
  461. n := btLoad(handle, cur)
  462. if n == nil {
  463. return rootPID, 0, false, errors.New("load failed")
  464. }
  465. if n.isLeaf() {
  466. pos, found := btLeafFind(n, key)
  467. if found {
  468. return rootPID, btPID(btEntry(n, pos)), true, nil
  469. }
  470. el := 12
  471. ne := make([]byte, el)
  472. copy(ne[:8], key)
  473. btSetPID(ne, dpID)
  474. ip := btLeafPos(n, key)
  475. if int(n.info.Hdr.UseSize)+el <= btSplitThreshold() {
  476. btInsEntry(n, ne, ip)
  477. btSave(handle, n)
  478. return rootPID, 0, false, nil
  479. }
  480. cnt := int(n.info.Count)
  481. total := cnt + 1
  482. all := make([]byte, total*el)
  483. if ip > 0 {
  484. copy(all, n.entries[:ip*el])
  485. }
  486. copy(all[ip*el:], ne)
  487. if cnt > ip {
  488. copy(all[(ip+1)*el:], n.entries[ip*el:cnt*el])
  489. }
  490. mid := total / 2
  491. // <= 路由约定: 左子叶所有 key 必须严格小于右子叶第一个 key (promoKey)
  492. // 如果 all[mid-1].key == all[mid].key, 右移 mid 直到分隔
  493. for mid < total-1 {
  494. if btCmp(all[(mid-1)*el:mid*el-4], all[mid*el:(mid+1)*el-4]) < 0 {
  495. break
  496. }
  497. mid++
  498. }
  499. rl := btNew(handle, true, el)
  500. rc := total - mid
  501. copy(rl.entries, all[mid*el:total*el])
  502. rl.info.Count = uint32(rc)
  503. rl.info.Hdr.UseSize = uint32(page.IndexHeadSize) + uint32(rc*el)
  504. rl.info.Hdr.NextPage = n.info.Hdr.NextPage
  505. rl.info.Hdr.PrePage = n.info.Hdr.PageID
  506. n.info.Hdr.NextPage = rl.info.Hdr.PageID
  507. copy(n.entries, all[:mid*el])
  508. n.info.Count = uint32(mid)
  509. n.info.Hdr.UseSize = uint32(page.IndexHeadSize) + uint32(mid*el)
  510. btSave(handle, n)
  511. btSave(handle, rl)
  512. if rl.info.Hdr.NextPage != 0 {
  513. nl := btLoad(handle, rl.info.Hdr.NextPage)
  514. if nl != nil {
  515. nl.info.Hdr.PrePage = rl.info.Hdr.PageID
  516. btSave(handle, nl)
  517. }
  518. }
  519. // 使用右子树最左叶的第一个 key 作为 promoKey
  520. pk := btLeftmostKey(handle, rl.info.Hdr.PageID)
  521. nr, err := btPromote(handle, rootPID, path, n.info.Hdr.PageID, pk, rl.info.Hdr.PageID)
  522. return nr, 0, false, err
  523. }
  524. ci := btChildIdx(n, key)
  525. cpid := btPID(btEntry(n, ci))
  526. path = append(path, btPathEntry{nodePID: cur, childIdx: ci})
  527. cur = cpid
  528. }
  529. }
  530. func btPromote(handle page.HandleDb, rootPID uint32, path []btPathEntry, leftPID uint32, promoKey []byte, rightPID uint32) (uint32, error) {
  531. if len(path) == 0 {
  532. el := 12
  533. nr := btNew(handle, false, el)
  534. leftKey := btLeftmostKey(handle, leftPID)
  535. le := make([]byte, el)
  536. copy(le[:8], leftKey)
  537. btSetPID(le, leftPID)
  538. re := make([]byte, el)
  539. copy(re[:8], promoKey)
  540. btSetPID(re, rightPID)
  541. btInsEntry(nr, le, 0)
  542. btInsEntry(nr, re, 1)
  543. btSave(handle, nr)
  544. return nr.pageID(), nil
  545. }
  546. pi := len(path) - 1
  547. parent := btLoad(handle, path[pi].nodePID)
  548. if parent == nil {
  549. return rootPID, errors.New("parent load failed")
  550. }
  551. ci := path[pi].childIdx
  552. el := int(parent.info.EntryLen)
  553. ok := make([]byte, el-4)
  554. copy(ok, btKey(btEntry(parent, ci)))
  555. // 叶子分裂后: 左半部分=原节点(保持 ok), 右半部分=新节点(需要 promoKey)
  556. // 更新 entry[ci] = (ok, leftPID) — key 不变, 只更新 PID
  557. btSetPID(btEntry(parent, ci), leftPID)
  558. // 在排序位置插入 (promoKey, rightPID)
  559. newPos := int(parent.info.Count)
  560. for i := ci + 1; i < int(parent.info.Count); i++ {
  561. if btCmp(btKey(btEntry(parent, i)), promoKey) >= 0 {
  562. newPos = i
  563. break
  564. }
  565. }
  566. for i := int(parent.info.Count); i > newPos; i-- {
  567. copy(btEntry(parent, i), btEntry(parent, i-1))
  568. }
  569. ne := make([]byte, el)
  570. copy(ne[:el-4], promoKey)
  571. btSetPID(ne, rightPID)
  572. copy(btEntry(parent, newPos), ne)
  573. parent.info.Count++
  574. parent.info.Hdr.UseSize += uint32(el)
  575. if int(parent.info.Hdr.UseSize)+el <= btSplitThreshold() {
  576. btSave(handle, parent)
  577. return rootPID, nil
  578. }
  579. cnt := int(parent.info.Count)
  580. mid := cnt / 2
  581. rn := btNew(handle, false, el)
  582. rc := cnt - mid
  583. copy(rn.entries, parent.entries[mid*el:cnt*el])
  584. rn.info.Count = uint32(rc)
  585. rn.info.Hdr.UseSize = uint32(page.IndexHeadSize) + uint32(rc*el)
  586. parent.info.Count = uint32(mid)
  587. parent.info.Hdr.UseSize = uint32(page.IndexHeadSize) + uint32(mid*el)
  588. btSave(handle, parent)
  589. btSave(handle, rn)
  590. pk2 := make([]byte, 8)
  591. copy(pk2, btKey(btEntry(rn, 0)))
  592. return btPromote(handle, rootPID, path[:pi], parent.info.Hdr.PageID, pk2, rn.info.Hdr.PageID)
  593. }
  594. // ======================== B+ 鏍戝垹闄?(閫掑綊 + 鍚堝苟/鍊熶綅) ========================
  595. func BTreePKDelete(rootPID uint32, key []byte, handle page.HandleDb) (uint32, uint32, error) {
  596. if rootPID == 0 {
  597. return 0, 0, page.ErrNotFound
  598. }
  599. delDP, err := btDeleteRec(rootPID, key, nil, handle)
  600. if err != nil {
  601. return rootPID, delDP, err
  602. }
  603. n := btLoad(handle, rootPID)
  604. if n != nil && n.info.Count == 0 {
  605. if !n.isLeaf() && n.info.Count == 0 {
  606. return rootPID, delDP, nil
  607. }
  608. }
  609. return rootPID, delDP, nil
  610. }
  611. func btDeleteRec(nodePID uint32, key []byte, path []btPathEntry, handle page.HandleDb) (uint32, error) {
  612. node := btLoad(handle, nodePID)
  613. if node == nil {
  614. return nodePID, page.ErrNotFound
  615. }
  616. el := int(node.info.EntryLen)
  617. if node.isLeaf() {
  618. pos, ok := btLeafFind(node, key)
  619. if !ok {
  620. return nodePID, page.ErrNotFound
  621. }
  622. delDP := btPID(btEntry(node, pos))
  623. btRmEntry(node, pos)
  624. if node.info.Count == 0 && len(path) == 0 {
  625. btSave(handle, node)
  626. return delDP, nil
  627. }
  628. btSave(handle, node)
  629. if len(path) > 0 && node.info.Count > 0 {
  630. btTryMerge(handle, path, node, el)
  631. }
  632. return delDP, nil
  633. }
  634. ci := btChildIdx(node, key)
  635. childPID := btPID(btEntry(node, ci))
  636. newPath := make([]btPathEntry, len(path)+1)
  637. copy(newPath, path)
  638. newPath[len(path)] = btPathEntry{nodePID: nodePID, childIdx: ci}
  639. delDP, err := btDeleteRec(childPID, key, newPath, handle)
  640. if err != nil {
  641. return delDP, err
  642. }
  643. node = btLoad(handle, nodePID)
  644. if node == nil {
  645. return delDP, errors.New("reload node failed")
  646. }
  647. if node.info.Count > 0 {
  648. ci2 := btChildIdx(node, key)
  649. if ci2 >= 0 && ci2 < int(node.info.Count) {
  650. cpID := btPID(btEntry(node, ci2))
  651. child := btLoad(handle, cpID)
  652. if child != nil && child.info.Count == 0 {
  653. btHandleUnderflow(node, ci2, el, handle)
  654. }
  655. }
  656. }
  657. if node.info.Count == 0 {
  658. return delDP, nil
  659. }
  660. btSave(handle, node)
  661. return delDP, nil
  662. }
  663. func btTryMerge(handle page.HandleDb, path []btPathEntry, node *btNode, el int) {
  664. if len(path) == 0 {
  665. return
  666. }
  667. pp := path[len(path)-1].nodePID
  668. parent := btLoad(handle, pp)
  669. if parent == nil {
  670. return
  671. }
  672. ci := -1
  673. for i := 0; i < int(parent.info.Count); i++ {
  674. if btPID(btEntry(parent, i)) == node.info.Hdr.PageID {
  675. ci = i
  676. break
  677. }
  678. }
  679. if ci < 0 {
  680. return
  681. }
  682. if ci > 0 {
  683. leftPID := btPID(btEntry(parent, ci-1))
  684. left := btLoad(handle, leftPID)
  685. if left != nil && left.isLeaf() {
  686. combined := uint32(page.IndexHeadSize) + (left.info.Count+node.info.Count)*uint32(el)
  687. threshold := uint32(btSplitThreshold())
  688. if combined <= threshold {
  689. rc := int(node.info.Count)
  690. copy(left.entries[int(left.info.Count)*el:], node.entries[:rc*el])
  691. left.info.Count += node.info.Count
  692. left.info.Hdr.UseSize += uint32(rc * el)
  693. left.info.Hdr.NextPage = node.info.Hdr.NextPage
  694. btSave(handle, left)
  695. if left.info.Hdr.NextPage != 0 {
  696. nl := btLoad(handle, left.info.Hdr.NextPage)
  697. if nl != nil {
  698. nl.info.Hdr.PrePage = leftPID
  699. btSave(handle, nl)
  700. }
  701. }
  702. btRmEntry(parent, ci)
  703. btSave(handle, parent)
  704. return
  705. }
  706. }
  707. }
  708. if ci < int(parent.info.Count)-1 {
  709. rightPID := btPID(btEntry(parent, ci+1))
  710. right := btLoad(handle, rightPID)
  711. if right != nil && right.isLeaf() {
  712. combined := uint32(page.IndexHeadSize) + (node.info.Count+right.info.Count)*uint32(el)
  713. threshold := uint32(btSplitThreshold())
  714. if combined <= threshold {
  715. rc := int(right.info.Count)
  716. copy(node.entries[int(node.info.Count)*el:], right.entries[:rc*el])
  717. node.info.Count += right.info.Count
  718. node.info.Hdr.UseSize += uint32(rc * el)
  719. node.info.Hdr.NextPage = right.info.Hdr.NextPage
  720. btSave(handle, node)
  721. if node.info.Hdr.NextPage != 0 {
  722. nl := btLoad(handle, node.info.Hdr.NextPage)
  723. if nl != nil {
  724. nl.info.Hdr.PrePage = node.info.Hdr.PageID
  725. btSave(handle, nl)
  726. }
  727. }
  728. btRmEntry(parent, ci+1)
  729. btSave(handle, parent)
  730. return
  731. }
  732. }
  733. }
  734. }
  735. func btHandleUnderflow(parent *btNode, childIdx int, el int, handle page.HandleDb) {
  736. childPID := btPID(btEntry(parent, childIdx))
  737. child := btLoad(handle, childPID)
  738. if child == nil {
  739. return
  740. }
  741. if childIdx > 0 {
  742. leftPID := btPID(btEntry(parent, childIdx-1))
  743. leftSib := btLoad(handle, leftPID)
  744. if leftSib != nil && int(leftSib.info.Count) > 1 {
  745. borrowed := make([]byte, el)
  746. copy(borrowed, btEntry(leftSib, int(leftSib.info.Count)-1))
  747. btRmEntry(leftSib, int(leftSib.info.Count)-1)
  748. btInsEntry(child, borrowed, 0)
  749. copy(btEntry(parent, childIdx)[:8], btKey(btEntry(child, 0)))
  750. btSave(handle, leftSib)
  751. btSave(handle, child)
  752. btSave(handle, parent)
  753. return
  754. }
  755. }
  756. if childIdx < int(parent.info.Count)-1 {
  757. rightPID := btPID(btEntry(parent, childIdx+1))
  758. rightSib := btLoad(handle, rightPID)
  759. if rightSib != nil && int(rightSib.info.Count) > 1 {
  760. borrowed := make([]byte, el)
  761. copy(borrowed, btEntry(rightSib, 0))
  762. btRmEntry(rightSib, 0)
  763. btInsEntry(child, borrowed, int(child.info.Count))
  764. copy(btEntry(parent, childIdx)[:8], btKey(btEntry(rightSib, 0)))
  765. btSave(handle, rightSib)
  766. btSave(handle, child)
  767. btSave(handle, parent)
  768. return
  769. }
  770. }
  771. if childIdx > 0 {
  772. btMergeChildren(handle, parent, childIdx-1, el)
  773. } else if childIdx < int(parent.info.Count)-1 {
  774. btMergeChildren(handle, parent, childIdx, el)
  775. }
  776. }
  777. func btMergeChildren(handle page.HandleDb, parent *btNode, sepIdx int, el int) {
  778. leftPID := btPID(btEntry(parent, sepIdx))
  779. rightPID := btPID(btEntry(parent, sepIdx+1))
  780. left := btLoad(handle, leftPID)
  781. right := btLoad(handle, rightPID)
  782. if left == nil || right == nil {
  783. return
  784. }
  785. if left.isLeaf() {
  786. rc := int(right.info.Count)
  787. copy(left.entries[int(left.info.Count)*el:], right.entries[:rc*el])
  788. left.info.Count += right.info.Count
  789. left.info.Hdr.UseSize += uint32(rc * el)
  790. left.info.Hdr.NextPage = right.info.Hdr.NextPage
  791. } else {
  792. sepEntry := make([]byte, el)
  793. copy(sepEntry, btEntry(parent, sepIdx))
  794. rc := int(right.info.Count)
  795. off := int(left.info.Count) * el
  796. copy(left.entries[off:], sepEntry)
  797. off += el
  798. copy(left.entries[off:], right.entries[:rc*el])
  799. left.info.Count += 1 + right.info.Count
  800. left.info.Hdr.UseSize += uint32((1 + rc) * el)
  801. }
  802. btSave(handle, left)
  803. if left.isLeaf() && left.info.Hdr.NextPage != 0 {
  804. nl := btLoad(handle, left.info.Hdr.NextPage)
  805. if nl != nil {
  806. nl.info.Hdr.PrePage = leftPID
  807. btSave(handle, nl)
  808. }
  809. }
  810. btRmEntry(parent, sepIdx+1)
  811. btSetPID(btEntry(parent, sepIdx), leftPID)
  812. btSave(handle, parent)
  813. }
  814. // ======================== DataPage 鎿嶄綔 ========================
  815. // FindSpaceInLeaf 鍦ㄥ彾鑺傜偣涓壘鍒版湁绌洪棿鐨?DataPage
  816. func FindSpaceInLeaf(handle page.HandleDb, rootPID uint32, rowSize uint32, key []byte) (uint32, bool) {
  817. cur := rootPID
  818. for {
  819. n := btLoad(handle, cur)
  820. if n == nil {
  821. return 0, false
  822. }
  823. if n.isLeaf() {
  824. pos := btLeafPos(n, key)
  825. if pos >= int(n.info.Count) {
  826. pos = int(n.info.Count) - 1
  827. }
  828. if pos < 0 {
  829. return 0, false
  830. }
  831. dpID := btPID(btEntry(n, pos))
  832. dp, err := datapage.Load(handle, dpID)
  833. if err == nil && !dp.IsFull(rowSize) {
  834. return dpID, true
  835. }
  836. if n.info.Hdr.PrePage != 0 {
  837. prevN := btLoad(handle, n.info.Hdr.PrePage)
  838. if prevN != nil && prevN.isLeaf() && prevN.info.Count > 0 {
  839. prevDPID := btPID(btEntry(prevN, int(prevN.info.Count)-1))
  840. prevDP, err := datapage.Load(handle, prevDPID)
  841. if err == nil && !prevDP.IsFull(rowSize) {
  842. return prevDPID, true
  843. }
  844. }
  845. }
  846. if n.info.Hdr.NextPage != 0 {
  847. nextN := btLoad(handle, n.info.Hdr.NextPage)
  848. if nextN != nil && nextN.isLeaf() && nextN.info.Count > 0 {
  849. nextDPID := btPID(btEntry(nextN, 0))
  850. nextDP, err := datapage.Load(handle, nextDPID)
  851. if err == nil && !nextDP.IsFull(rowSize) {
  852. return nextDPID, true
  853. }
  854. }
  855. }
  856. return 0, false
  857. }
  858. cur = btRoute(n, key)
  859. }
  860. }
  861. // FindLastLeafDP 路由到目标叶子, 检查最后一个条目的 DataPage 是否有空间
  862. // 只检查路由目标叶子, 不跨叶子查找 (保证 B+ 树不变性)
  863. func FindLastLeafDP(handle page.HandleDb, rootPID uint32, rowSize uint32, key []byte) (uint32, bool) {
  864. cur := rootPID
  865. for {
  866. n := btLoad(handle, cur)
  867. if n == nil {
  868. return 0, false
  869. }
  870. if n.isLeaf() {
  871. if n.info.Count == 0 {
  872. return 0, false
  873. }
  874. // 检查最后一个条目的 DataPage
  875. lastIdx := int(n.info.Count) - 1
  876. dpID := btPID(btEntry(n, lastIdx))
  877. dp, err := datapage.Load(handle, dpID)
  878. if err == nil && !dp.IsFull(rowSize) {
  879. return dpID, true
  880. }
  881. return 0, false
  882. }
  883. cur = btRoute(n, key)
  884. }
  885. }
  886. // GetDataPageIDs 返回所有 DataPage ID (去重, 用于全表扫描)
  887. func GetDataPageIDs(handle page.HandleDb, rootPID uint32) []uint32 {
  888. if rootPID == 0 {
  889. return nil
  890. }
  891. var dpIDs []uint32
  892. seen := make(map[uint32]bool)
  893. cur := rootPID
  894. for {
  895. n := btLoad(handle, cur)
  896. if n == nil {
  897. break
  898. }
  899. if n.isLeaf() {
  900. break
  901. }
  902. cur = btPID(btEntry(n, 0))
  903. }
  904. for cur != 0 {
  905. n := btLoad(handle, cur)
  906. if n == nil {
  907. break
  908. }
  909. for i := 0; i < int(n.info.Count); i++ {
  910. dpID := btPID(btEntry(n, i))
  911. if !seen[dpID] {
  912. seen[dpID] = true
  913. dpIDs = append(dpIDs, dpID)
  914. }
  915. }
  916. cur = n.info.Hdr.NextPage
  917. }
  918. return dpIDs
  919. }
  920. // ScanAllLeavesForPK 扫描所有叶子查找 pkID(LE)
  921. func ScanAllLeavesForPK(rootPID uint32, handle page.HandleDb, pkKeyBE []byte) ([]byte, bool) {
  922. if rootPID == 0 {
  923. return nil, false
  924. }
  925. cur := rootPID
  926. for {
  927. n := btLoad(handle, cur)
  928. if n == nil {
  929. return nil, false
  930. }
  931. if n.isLeaf() {
  932. break
  933. }
  934. cur = btPID(btEntry(n, 0))
  935. }
  936. for cur != 0 {
  937. n := btLoad(handle, cur)
  938. if n == nil {
  939. break
  940. }
  941. for i := 0; i < int(n.info.Count); i++ {
  942. dpID := btPID(btEntry(n, i))
  943. dp, err := datapage.Load(handle, dpID)
  944. if err == nil {
  945. if rowData, ok := dp.FindRowByPK(pkKeyBE); ok {
  946. return rowData, true
  947. }
  948. }
  949. }
  950. cur = n.info.Hdr.NextPage
  951. }
  952. return nil, false
  953. }
  954. // ScanAndDelete 扫描所有叶子按 indexKey 删除
  955. func ScanAndDelete(rootPID uint32, handle page.HandleDb, indexKey, pkKeyBE []byte) error {
  956. if rootPID == 0 {
  957. return page.ErrNotFound
  958. }
  959. cur := rootPID
  960. for {
  961. n := btLoad(handle, cur)
  962. if n == nil {
  963. return page.ErrNotFound
  964. }
  965. if n.isLeaf() {
  966. break
  967. }
  968. cur = btPID(btEntry(n, 0))
  969. }
  970. for cur != 0 {
  971. n := btLoad(handle, cur)
  972. if n == nil {
  973. break
  974. }
  975. for i := 0; i < int(n.info.Count); i++ {
  976. dpID := btPID(btEntry(n, i))
  977. dp, err := datapage.Load(handle, dpID)
  978. if err == nil {
  979. deleted := false
  980. if dp.DeleteByIndexKey(indexKey, 8) {
  981. deleted = true
  982. } else if dp.DeleteByPK(pkKeyBE) {
  983. deleted = true
  984. }
  985. if deleted {
  986. if dp.AllDeleted() {
  987. newRoot, _, err := BTreePKDelete(rootPID, indexKey, handle)
  988. if err != nil {
  989. return err
  990. }
  991. _ = newRoot
  992. } else {
  993. dp.Save()
  994. }
  995. return nil
  996. }
  997. }
  998. }
  999. cur = n.info.Hdr.NextPage
  1000. }
  1001. return page.ErrNotFound
  1002. }
  1003. // ScanAndDeleteByPK 扫描所有叶子按 pkID 删除
  1004. func ScanAndDeleteByPK(rootPID uint32, handle page.HandleDb, pkKeyBE []byte) error {
  1005. if rootPID == 0 {
  1006. return page.ErrNotFound
  1007. }
  1008. cur := rootPID
  1009. for {
  1010. n := btLoad(handle, cur)
  1011. if n == nil {
  1012. return page.ErrNotFound
  1013. }
  1014. if n.isLeaf() {
  1015. break
  1016. }
  1017. cur = btPID(btEntry(n, 0))
  1018. }
  1019. for cur != 0 {
  1020. n := btLoad(handle, cur)
  1021. if n == nil {
  1022. break
  1023. }
  1024. for i := 0; i < int(n.info.Count); i++ {
  1025. dpID := btPID(btEntry(n, i))
  1026. dp, err := datapage.Load(handle, dpID)
  1027. if err == nil {
  1028. if dp.DeleteByPK(pkKeyBE) {
  1029. if dp.AllDeleted() {
  1030. newRoot, _, err := BTreePKDelete(rootPID, pkKeyBE, handle)
  1031. if err != nil {
  1032. return err
  1033. }
  1034. _ = newRoot
  1035. } else {
  1036. dp.Save()
  1037. }
  1038. return nil
  1039. }
  1040. }
  1041. }
  1042. cur = n.info.Hdr.NextPage
  1043. }
  1044. return page.ErrNotFound
  1045. }
  1046. // ScanAndUpdate 扫描所有叶子按 pkID 更新
  1047. func ScanAndUpdate(rootPID uint32, handle page.HandleDb, pkKeyBE, storeRowData []byte) error {
  1048. if rootPID == 0 {
  1049. return page.ErrNotFound
  1050. }
  1051. cur := rootPID
  1052. for {
  1053. n := btLoad(handle, cur)
  1054. if n == nil {
  1055. return page.ErrNotFound
  1056. }
  1057. if n.isLeaf() {
  1058. break
  1059. }
  1060. cur = btPID(btEntry(n, 0))
  1061. }
  1062. for cur != 0 {
  1063. n := btLoad(handle, cur)
  1064. if n == nil {
  1065. break
  1066. }
  1067. for i := 0; i < int(n.info.Count); i++ {
  1068. dpID := btPID(btEntry(n, i))
  1069. dp, err := datapage.Load(handle, dpID)
  1070. if err == nil {
  1071. if err := dp.UpdateByPK(pkKeyBE, storeRowData); err == nil {
  1072. dp.Save()
  1073. return nil
  1074. }
  1075. }
  1076. }
  1077. cur = n.info.Hdr.NextPage
  1078. }
  1079. return page.ErrNotFound
  1080. }
  1081. // BTreeValidate 检查 B+ 树内部节点条目排序
  1082. func BTreeValidate(handle page.HandleDb, rootPID uint32) []string {
  1083. var issues []string
  1084. if rootPID == 0 {
  1085. return issues
  1086. }
  1087. var check func(pid uint32, depth int)
  1088. check = func(pid uint32, depth int) {
  1089. n := btLoad(handle, pid)
  1090. if n == nil {
  1091. issues = append(issues, fmt.Sprintf("d=%d: load fail pid=%d", depth, pid))
  1092. return
  1093. }
  1094. cnt := int(n.info.Count)
  1095. if n.isLeaf() {
  1096. for i := 1; i < cnt; i++ {
  1097. pk := btKey(btEntry(n, i-1))
  1098. ck := btKey(btEntry(n, i))
  1099. if btCmp(pk, ck) >= 0 {
  1100. issues = append(issues, fmt.Sprintf("d=%d leaf=%d: unsorted [%d]>=[%d]", depth, pid, i-1, i))
  1101. }
  1102. }
  1103. return
  1104. }
  1105. for i := 1; i < cnt; i++ {
  1106. pk := btKey(btEntry(n, i-1))
  1107. ck := btKey(btEntry(n, i))
  1108. if btCmp(pk, ck) > 0 {
  1109. issues = append(issues, fmt.Sprintf("d=%d int=%d: UNSORTED [%d]>[%d]", depth, pid, i-1, i))
  1110. }
  1111. }
  1112. for i := 0; i < cnt; i++ {
  1113. childPID := btPID(btEntry(n, i))
  1114. check(childPID, depth+1)
  1115. }
  1116. }
  1117. check(rootPID, 0)
  1118. return issues
  1119. }
  1120. // BTreeTraceSearch 搜索并打印路由路径
  1121. func BTreeTraceSearch(rootPID uint32, key []byte, handle page.HandleDb) {
  1122. if rootPID == 0 {
  1123. fmt.Println("Tree is empty")
  1124. return
  1125. }
  1126. cur := rootPID
  1127. depth := 0
  1128. for {
  1129. n := btLoad(handle, cur)
  1130. if n == nil {
  1131. fmt.Printf(" d=%d: LOAD FAIL pid=%d\n", depth, cur)
  1132. return
  1133. }
  1134. el := int(n.info.EntryLen)
  1135. cnt := int(n.info.Count)
  1136. if n.isLeaf() {
  1137. fk := uint64(0)
  1138. lk := uint64(0)
  1139. if cnt > 0 {
  1140. fk = binary.BigEndian.Uint64(btKey(btEntry(n, 0)))
  1141. lk = binary.BigEndian.Uint64(btKey(btEntry(n, cnt-1)))
  1142. }
  1143. pos, found := btLeafFind(n, key)
  1144. fmt.Printf(" d=%d LEAF pid=%d cnt=%d first=%d last=%d pos=%d found=%v\n",
  1145. depth, cur, cnt, fk, lk, pos, found)
  1146. return
  1147. }
  1148. fmt.Printf(" d=%d INT pid=%d cnt=%d [", depth, cur, cnt)
  1149. for i := 0; i < cnt; i++ {
  1150. k := binary.BigEndian.Uint64(btEntry(n, i)[:el-4])
  1151. p := btPID(btEntry(n, i))
  1152. if i > 0 {
  1153. fmt.Printf(", ")
  1154. }
  1155. if i < 3 || i >= cnt-2 {
  1156. fmt.Printf("(k=%d,p=%d)", k, p)
  1157. } else if i == 3 {
  1158. fmt.Printf("...")
  1159. }
  1160. }
  1161. fmt.Printf("]\n")
  1162. ci := btChildIdx(n, key)
  1163. fmt.Printf(" btChildIdx(%d) = %d\n", binary.BigEndian.Uint64(key), ci)
  1164. cur = btPID(btEntry(n, ci))
  1165. depth++
  1166. }
  1167. }
  1168. // CollectAllPageIDs 收集 B+ 树所有页 ID (包括内部节点和叶子节点)
  1169. // 用于 DropTable 时释放所有 B+ 树占用的页
  1170. func CollectAllPageIDs(handle page.HandleDb, rootPID uint32) []uint32 {
  1171. if rootPID == 0 {
  1172. return nil
  1173. }
  1174. var pages []uint32
  1175. // BFS 遍历所有节点
  1176. queue := []uint32{rootPID}
  1177. for len(queue) > 0 {
  1178. pid := queue[0]
  1179. queue = queue[1:]
  1180. pages = append(pages, pid)
  1181. n := btLoad(handle, pid)
  1182. if n == nil {
  1183. continue
  1184. }
  1185. if !n.isLeaf() {
  1186. // 内部节点: 收集所有子节点
  1187. for i := 0; i < int(n.info.Count); i++ {
  1188. childPID := btPID(btEntry(n, i))
  1189. if childPID != 0 {
  1190. queue = append(queue, childPID)
  1191. }
  1192. }
  1193. }
  1194. }
  1195. return pages
  1196. }