You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

btree.go 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. // Copyright 2020 Joshua J Baker. All rights reserved.
  2. // Use of this source code is governed by an MIT-style
  3. // license that can be found in the LICENSE file.
  4. package btree
  5. import "sync"
  6. const maxItems = 255
  7. const minItems = maxItems * 40 / 100
  8. type cow struct {
  9. _ int // it cannot be an empty struct
  10. }
  11. type node struct {
  12. cow *cow
  13. leaf bool
  14. numItems int16
  15. items [maxItems]interface{}
  16. children *[maxItems + 1]*node
  17. }
  18. // BTree is an ordered set items
  19. type BTree struct {
  20. mu *sync.RWMutex
  21. cow *cow
  22. root *node
  23. length int
  24. less func(a, b interface{}) bool
  25. lnode *node
  26. }
  27. func (tr *BTree) newNode(leaf bool) *node {
  28. n := &node{leaf: leaf}
  29. if !leaf {
  30. n.children = new([maxItems + 1]*node)
  31. }
  32. n.cow = tr.cow
  33. return n
  34. }
  35. // PathHint is a utility type used with the *Hint() functions. Hints provide
  36. // faster operations for clustered keys.
  37. type PathHint struct {
  38. path [8]uint8
  39. }
  40. // New returns a new BTree
  41. func New(less func(a, b interface{}) bool) *BTree {
  42. if less == nil {
  43. panic("nil less")
  44. }
  45. tr := new(BTree)
  46. tr.mu = new(sync.RWMutex)
  47. tr.less = less
  48. return tr
  49. }
  50. // Less is a convenience function that performs a comparison of two items
  51. // using the same "less" function provided to New.
  52. func (tr *BTree) Less(a, b interface{}) bool {
  53. return tr.less(a, b)
  54. }
  55. func (n *node) find(key interface{}, less func(a, b interface{}) bool,
  56. hint *PathHint, depth int,
  57. ) (index int16, found bool) {
  58. low := int16(0)
  59. high := n.numItems - 1
  60. if hint != nil && depth < 8 {
  61. index = int16(hint.path[depth])
  62. if index > n.numItems-1 {
  63. index = n.numItems - 1
  64. }
  65. if less(key, n.items[index]) {
  66. high = index - 1
  67. } else if less(n.items[index], key) {
  68. low = index + 1
  69. } else {
  70. found = true
  71. goto done
  72. }
  73. }
  74. for low <= high {
  75. mid := low + ((high+1)-low)/2
  76. if !less(key, n.items[mid]) {
  77. low = mid + 1
  78. } else {
  79. high = mid - 1
  80. }
  81. }
  82. if low > 0 && !less(n.items[low-1], key) {
  83. index = low - 1
  84. found = true
  85. } else {
  86. index = low
  87. found = false
  88. }
  89. done:
  90. if hint != nil && depth < 8 {
  91. if n.leaf && found {
  92. hint.path[depth] = byte(index + 1)
  93. } else {
  94. hint.path[depth] = byte(index)
  95. }
  96. }
  97. return index, found
  98. }
  99. // SetHint sets or replace a value for a key using a path hint
  100. func (tr *BTree) SetHint(item interface{}, hint *PathHint) (prev interface{}) {
  101. if item == nil {
  102. panic("nil item")
  103. }
  104. tr.mu.Lock()
  105. prev = tr.setHint(item, hint)
  106. tr.mu.Unlock()
  107. return prev
  108. }
  109. func (tr *BTree) setHint(item interface{}, hint *PathHint) (prev interface{}) {
  110. if tr.root == nil {
  111. tr.root = tr.newNode(true)
  112. tr.root.items[0] = item
  113. tr.root.numItems = 1
  114. tr.length = 1
  115. return
  116. }
  117. prev = tr.nodeSet(&tr.root, item, tr.less, hint, 0)
  118. if prev != nil {
  119. return prev
  120. }
  121. tr.lnode = nil
  122. if tr.root.numItems == maxItems {
  123. n := tr.cowLoad(&tr.root)
  124. right, median := tr.nodeSplit(n)
  125. tr.root = tr.newNode(false)
  126. tr.root.children[0] = n
  127. tr.root.items[0] = median
  128. tr.root.children[1] = right
  129. tr.root.numItems = 1
  130. }
  131. tr.length++
  132. return prev
  133. }
  134. // Set or replace a value for a key
  135. func (tr *BTree) Set(item interface{}) (prev interface{}) {
  136. return tr.SetHint(item, nil)
  137. }
  138. func (tr *BTree) nodeSplit(n *node) (right *node, median interface{}) {
  139. right = tr.newNode(n.leaf)
  140. median = n.items[maxItems/2]
  141. copy(right.items[:maxItems/2], n.items[maxItems/2+1:])
  142. if !n.leaf {
  143. copy(right.children[:maxItems/2+1], n.children[maxItems/2+1:])
  144. }
  145. right.numItems = maxItems / 2
  146. if !n.leaf {
  147. for i := maxItems/2 + 1; i < maxItems+1; i++ {
  148. n.children[i] = nil
  149. }
  150. }
  151. for i := maxItems / 2; i < maxItems; i++ {
  152. n.items[i] = nil
  153. }
  154. n.numItems = maxItems / 2
  155. return right, median
  156. }
  157. //go:noinline
  158. func (tr *BTree) copy(n *node) *node {
  159. n2 := *n
  160. n2.cow = tr.cow
  161. copy(n2.items[:], n.items[:])
  162. if n.children != nil {
  163. n2.children = new([maxItems + 1]*node)
  164. copy(n2.children[:], n.children[:])
  165. }
  166. return &n2
  167. }
  168. // cowLoad loaded the provide node and, if needed, performs a copy-on-write.
  169. func (tr *BTree) cowLoad(cn **node) *node {
  170. if (*cn).cow != tr.cow {
  171. *cn = tr.copy(*cn)
  172. }
  173. return *cn
  174. }
  175. func (tr *BTree) nodeSet(cn **node, item interface{},
  176. less func(a, b interface{}) bool, hint *PathHint, depth int,
  177. ) (prev interface{}) {
  178. n := tr.cowLoad(cn)
  179. i, found := n.find(item, less, hint, depth)
  180. if found {
  181. prev = n.items[i]
  182. n.items[i] = item
  183. return prev
  184. }
  185. if n.leaf {
  186. copy(n.items[i+1:n.numItems+1], n.items[i:n.numItems])
  187. n.items[i] = item
  188. n.numItems++
  189. return nil
  190. }
  191. prev = tr.nodeSet(&n.children[i], item, less, hint, depth+1)
  192. if prev != nil {
  193. return prev
  194. }
  195. if n.children[i].numItems == maxItems {
  196. right, median := tr.nodeSplit(n.children[i])
  197. copy(n.children[i+1:], n.children[i:])
  198. copy(n.items[i+1:], n.items[i:])
  199. n.items[i] = median
  200. n.children[i+1] = right
  201. n.numItems++
  202. }
  203. return prev
  204. }
  205. func (n *node) scan(iter func(item interface{}) bool) bool {
  206. if n.leaf {
  207. for i := int16(0); i < n.numItems; i++ {
  208. if !iter(n.items[i]) {
  209. return false
  210. }
  211. }
  212. return true
  213. }
  214. for i := int16(0); i < n.numItems; i++ {
  215. if !n.children[i].scan(iter) {
  216. return false
  217. }
  218. if !iter(n.items[i]) {
  219. return false
  220. }
  221. }
  222. return n.children[n.numItems].scan(iter)
  223. }
  224. // Get a value for key
  225. func (tr *BTree) Get(key interface{}) interface{} {
  226. return tr.GetHint(key, nil)
  227. }
  228. // GetHint gets a value for key using a path hint
  229. func (tr *BTree) GetHint(key interface{}, hint *PathHint) interface{} {
  230. tr.mu.RLock()
  231. defer tr.mu.RUnlock()
  232. if tr.root == nil || key == nil {
  233. return nil
  234. }
  235. depth := 0
  236. n := tr.root
  237. for {
  238. i, found := n.find(key, tr.less, hint, depth)
  239. if found {
  240. return n.items[i]
  241. }
  242. if n.leaf {
  243. return nil
  244. }
  245. n = n.children[i]
  246. depth++
  247. }
  248. }
  249. // Len returns the number of items in the tree
  250. func (tr *BTree) Len() int {
  251. return tr.length
  252. }
  253. // Delete a value for a key
  254. func (tr *BTree) Delete(key interface{}) interface{} {
  255. return tr.DeleteHint(key, nil)
  256. }
  257. // DeleteHint deletes a value for a key using a path hint
  258. func (tr *BTree) DeleteHint(key interface{}, hint *PathHint) interface{} {
  259. tr.mu.Lock()
  260. prev := tr.deleteHint(key, hint)
  261. tr.mu.Unlock()
  262. return prev
  263. }
  264. func (tr *BTree) deleteHint(key interface{}, hint *PathHint) interface{} {
  265. if tr.root == nil || key == nil {
  266. return nil
  267. }
  268. prev := tr.delete(&tr.root, false, key, tr.less, hint, 0)
  269. if prev == nil {
  270. return nil
  271. }
  272. tr.lnode = nil
  273. if tr.root.numItems == 0 && !tr.root.leaf {
  274. tr.root = tr.root.children[0]
  275. }
  276. tr.length--
  277. if tr.length == 0 {
  278. tr.root = nil
  279. }
  280. return prev
  281. }
  282. func (tr *BTree) delete(cn **node, max bool, key interface{},
  283. less func(a, b interface{}) bool, hint *PathHint, depth int,
  284. ) interface{} {
  285. n := tr.cowLoad(cn)
  286. var i int16
  287. var found bool
  288. if max {
  289. i, found = n.numItems-1, true
  290. } else {
  291. i, found = n.find(key, less, hint, depth)
  292. }
  293. if n.leaf {
  294. if found {
  295. prev := n.items[i]
  296. // found the items at the leaf, remove it and return.
  297. copy(n.items[i:], n.items[i+1:n.numItems])
  298. n.items[n.numItems-1] = nil
  299. n.numItems--
  300. return prev
  301. }
  302. return nil
  303. }
  304. var prev interface{}
  305. if found {
  306. if max {
  307. i++
  308. prev = tr.delete(&n.children[i], true, "", less, nil, 0)
  309. } else {
  310. prev = n.items[i]
  311. maxItem := tr.delete(&n.children[i], true, "", less, nil, 0)
  312. n.items[i] = maxItem
  313. }
  314. } else {
  315. prev = tr.delete(&n.children[i], max, key, less, hint, depth+1)
  316. }
  317. if prev == nil {
  318. return nil
  319. }
  320. if n.children[i].numItems >= minItems {
  321. return prev
  322. }
  323. // merge / rebalance nodes
  324. if i == n.numItems {
  325. i--
  326. }
  327. n.children[i] = tr.cowLoad(&n.children[i])
  328. n.children[i+1] = tr.cowLoad(&n.children[i+1])
  329. if n.children[i].numItems+n.children[i+1].numItems+1 < maxItems {
  330. // merge left + item + right
  331. n.children[i].items[n.children[i].numItems] = n.items[i]
  332. copy(n.children[i].items[n.children[i].numItems+1:],
  333. n.children[i+1].items[:n.children[i+1].numItems])
  334. if !n.children[0].leaf {
  335. copy(n.children[i].children[n.children[i].numItems+1:],
  336. n.children[i+1].children[:n.children[i+1].numItems+1])
  337. }
  338. n.children[i].numItems += n.children[i+1].numItems + 1
  339. copy(n.items[i:], n.items[i+1:n.numItems])
  340. copy(n.children[i+1:], n.children[i+2:n.numItems+1])
  341. n.items[n.numItems] = nil
  342. n.children[n.numItems+1] = nil
  343. n.numItems--
  344. } else if n.children[i].numItems > n.children[i+1].numItems {
  345. // move left -> right
  346. copy(n.children[i+1].items[1:],
  347. n.children[i+1].items[:n.children[i+1].numItems])
  348. if !n.children[0].leaf {
  349. copy(n.children[i+1].children[1:],
  350. n.children[i+1].children[:n.children[i+1].numItems+1])
  351. }
  352. n.children[i+1].items[0] = n.items[i]
  353. if !n.children[0].leaf {
  354. n.children[i+1].children[0] =
  355. n.children[i].children[n.children[i].numItems]
  356. }
  357. n.children[i+1].numItems++
  358. n.items[i] = n.children[i].items[n.children[i].numItems-1]
  359. n.children[i].items[n.children[i].numItems-1] = nil
  360. if !n.children[0].leaf {
  361. n.children[i].children[n.children[i].numItems] = nil
  362. }
  363. n.children[i].numItems--
  364. } else {
  365. // move right -> left
  366. n.children[i].items[n.children[i].numItems] = n.items[i]
  367. if !n.children[0].leaf {
  368. n.children[i].children[n.children[i].numItems+1] =
  369. n.children[i+1].children[0]
  370. }
  371. n.children[i].numItems++
  372. n.items[i] = n.children[i+1].items[0]
  373. copy(n.children[i+1].items[:],
  374. n.children[i+1].items[1:n.children[i+1].numItems])
  375. if !n.children[0].leaf {
  376. copy(n.children[i+1].children[:],
  377. n.children[i+1].children[1:n.children[i+1].numItems+1])
  378. }
  379. n.children[i+1].numItems--
  380. }
  381. return prev
  382. }
  383. // Ascend the tree within the range [pivot, last]
  384. // Pass nil for pivot to scan all item in ascending order
  385. // Return false to stop iterating
  386. func (tr *BTree) Ascend(pivot interface{}, iter func(item interface{}) bool) {
  387. tr.mu.RLock()
  388. defer tr.mu.RUnlock()
  389. if tr.root == nil {
  390. return
  391. }
  392. if pivot == nil {
  393. tr.root.scan(iter)
  394. } else if tr.root != nil {
  395. tr.root.ascend(pivot, tr.less, nil, 0, iter)
  396. }
  397. }
  398. func (n *node) ascend(pivot interface{}, less func(a, b interface{}) bool,
  399. hint *PathHint, depth int, iter func(item interface{}) bool,
  400. ) bool {
  401. i, found := n.find(pivot, less, hint, depth)
  402. if !found {
  403. if !n.leaf {
  404. if !n.children[i].ascend(pivot, less, hint, depth+1, iter) {
  405. return false
  406. }
  407. }
  408. }
  409. for ; i < n.numItems; i++ {
  410. if !iter(n.items[i]) {
  411. return false
  412. }
  413. if !n.leaf {
  414. if !n.children[i+1].scan(iter) {
  415. return false
  416. }
  417. }
  418. }
  419. return true
  420. }
  421. func (n *node) reverse(iter func(item interface{}) bool) bool {
  422. if n.leaf {
  423. for i := n.numItems - 1; i >= 0; i-- {
  424. if !iter(n.items[i]) {
  425. return false
  426. }
  427. }
  428. return true
  429. }
  430. if !n.children[n.numItems].reverse(iter) {
  431. return false
  432. }
  433. for i := n.numItems - 1; i >= 0; i-- {
  434. if !iter(n.items[i]) {
  435. return false
  436. }
  437. if !n.children[i].reverse(iter) {
  438. return false
  439. }
  440. }
  441. return true
  442. }
  443. // Descend the tree within the range [pivot, first]
  444. // Pass nil for pivot to scan all item in descending order
  445. // Return false to stop iterating
  446. func (tr *BTree) Descend(pivot interface{}, iter func(item interface{}) bool) {
  447. tr.mu.RLock()
  448. defer tr.mu.RUnlock()
  449. if tr.root == nil {
  450. return
  451. }
  452. if pivot == nil {
  453. tr.root.reverse(iter)
  454. } else if tr.root != nil {
  455. tr.root.descend(pivot, tr.less, nil, 0, iter)
  456. }
  457. }
  458. func (n *node) descend(pivot interface{}, less func(a, b interface{}) bool,
  459. hint *PathHint, depth int, iter func(item interface{}) bool,
  460. ) bool {
  461. i, found := n.find(pivot, less, hint, depth)
  462. if !found {
  463. if !n.leaf {
  464. if !n.children[i].descend(pivot, less, hint, depth+1, iter) {
  465. return false
  466. }
  467. }
  468. i--
  469. }
  470. for ; i >= 0; i-- {
  471. if !iter(n.items[i]) {
  472. return false
  473. }
  474. if !n.leaf {
  475. if !n.children[i].reverse(iter) {
  476. return false
  477. }
  478. }
  479. }
  480. return true
  481. }
  482. // Load is for bulk loading pre-sorted items
  483. func (tr *BTree) Load(item interface{}) interface{} {
  484. if item == nil {
  485. panic("nil item")
  486. }
  487. tr.mu.Lock()
  488. defer tr.mu.Unlock()
  489. // Load does not need a cowGrid because the Copy operation sets the
  490. // lnode to nil.
  491. if tr.lnode != nil && tr.lnode.numItems < maxItems-2 {
  492. if tr.less(tr.lnode.items[tr.lnode.numItems-1], item) {
  493. tr.lnode.items[tr.lnode.numItems] = item
  494. tr.lnode.numItems++
  495. tr.length++
  496. return nil
  497. }
  498. }
  499. prev := tr.setHint(item, nil)
  500. if prev != nil {
  501. return prev
  502. }
  503. n := tr.root
  504. for {
  505. if n.leaf {
  506. tr.lnode = n
  507. break
  508. }
  509. n = n.children[n.numItems]
  510. }
  511. return nil
  512. }
  513. // Min returns the minimum item in tree.
  514. // Returns nil if the tree has no items.
  515. func (tr *BTree) Min() interface{} {
  516. tr.mu.RLock()
  517. defer tr.mu.RUnlock()
  518. if tr.root == nil {
  519. return nil
  520. }
  521. n := tr.root
  522. for {
  523. if n.leaf {
  524. return n.items[0]
  525. }
  526. n = n.children[0]
  527. }
  528. }
  529. // Max returns the maximum item in tree.
  530. // Returns nil if the tree has no items.
  531. func (tr *BTree) Max() interface{} {
  532. tr.mu.RLock()
  533. defer tr.mu.RUnlock()
  534. if tr.root == nil {
  535. return nil
  536. }
  537. n := tr.root
  538. for {
  539. if n.leaf {
  540. return n.items[n.numItems-1]
  541. }
  542. n = n.children[n.numItems]
  543. }
  544. }
  545. // PopMin removes the minimum item in tree and returns it.
  546. // Returns nil if the tree has no items.
  547. func (tr *BTree) PopMin() interface{} {
  548. tr.mu.Lock()
  549. defer tr.mu.Unlock()
  550. if tr.root == nil {
  551. return nil
  552. }
  553. tr.lnode = nil
  554. n := tr.cowLoad(&tr.root)
  555. for {
  556. if n.leaf {
  557. item := n.items[0]
  558. if n.numItems == minItems {
  559. return tr.deleteHint(item, nil)
  560. }
  561. copy(n.items[:], n.items[1:])
  562. n.items[n.numItems-1] = nil
  563. n.numItems--
  564. tr.length--
  565. if tr.length == 0 {
  566. tr.root = nil
  567. }
  568. return item
  569. }
  570. n = tr.cowLoad(&n.children[0])
  571. }
  572. }
  573. // PopMax removes the minimum item in tree and returns it.
  574. // Returns nil if the tree has no items.
  575. func (tr *BTree) PopMax() interface{} {
  576. tr.mu.Lock()
  577. defer tr.mu.Unlock()
  578. if tr.root == nil {
  579. return nil
  580. }
  581. tr.lnode = nil
  582. n := tr.cowLoad(&tr.root)
  583. for {
  584. if n.leaf {
  585. item := n.items[n.numItems-1]
  586. if n.numItems == minItems {
  587. return tr.deleteHint(item, nil)
  588. }
  589. n.items[n.numItems-1] = nil
  590. n.numItems--
  591. tr.length--
  592. if tr.length == 0 {
  593. tr.root = nil
  594. }
  595. return item
  596. }
  597. n = tr.cowLoad(&n.children[n.numItems])
  598. }
  599. }
  600. // Height returns the height of the tree.
  601. // Returns zero if tree has no items.
  602. func (tr *BTree) Height() int {
  603. tr.mu.RLock()
  604. defer tr.mu.RUnlock()
  605. var height int
  606. if tr.root != nil {
  607. n := tr.root
  608. for {
  609. height++
  610. if n.leaf {
  611. break
  612. }
  613. n = n.children[n.numItems]
  614. }
  615. }
  616. return height
  617. }
  618. // Walk iterates over all items in tree, in order.
  619. // The items param will contain one or more items.
  620. func (tr *BTree) Walk(iter func(item []interface{})) {
  621. tr.mu.RLock()
  622. defer tr.mu.RUnlock()
  623. if tr.root != nil {
  624. tr.root.walk(iter)
  625. }
  626. }
  627. func (n *node) walk(iter func(item []interface{})) {
  628. if n.leaf {
  629. iter(n.items[:n.numItems])
  630. } else {
  631. for i := int16(0); i < n.numItems; i++ {
  632. n.children[i].walk(iter)
  633. iter(n.items[i : i+1])
  634. }
  635. n.children[n.numItems].walk(iter)
  636. }
  637. }
  638. // Copy the tree. This operation is very fast because it only performs a
  639. // shadowed copy.
  640. func (tr *BTree) Copy() *BTree {
  641. tr.mu.Lock()
  642. tr.lnode = nil
  643. tr.cow = new(cow)
  644. tr2 := *tr
  645. tr2.mu = new(sync.RWMutex)
  646. tr2.cow = new(cow)
  647. tr.mu.Unlock()
  648. return &tr2
  649. }