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.

204 lines
4.9 KiB

  1. package bbolt
  2. import (
  3. "fmt"
  4. "os"
  5. "sort"
  6. "unsafe"
  7. )
  8. const pageHeaderSize = unsafe.Sizeof(page{})
  9. const minKeysPerPage = 2
  10. const branchPageElementSize = unsafe.Sizeof(branchPageElement{})
  11. const leafPageElementSize = unsafe.Sizeof(leafPageElement{})
  12. const (
  13. branchPageFlag = 0x01
  14. leafPageFlag = 0x02
  15. metaPageFlag = 0x04
  16. freelistPageFlag = 0x10
  17. )
  18. const (
  19. bucketLeafFlag = 0x01
  20. )
  21. type pgid uint64
  22. type page struct {
  23. id pgid
  24. flags uint16
  25. count uint16
  26. overflow uint32
  27. }
  28. // typ returns a human readable page type string used for debugging.
  29. func (p *page) typ() string {
  30. if (p.flags & branchPageFlag) != 0 {
  31. return "branch"
  32. } else if (p.flags & leafPageFlag) != 0 {
  33. return "leaf"
  34. } else if (p.flags & metaPageFlag) != 0 {
  35. return "meta"
  36. } else if (p.flags & freelistPageFlag) != 0 {
  37. return "freelist"
  38. }
  39. return fmt.Sprintf("unknown<%02x>", p.flags)
  40. }
  41. // meta returns a pointer to the metadata section of the page.
  42. func (p *page) meta() *meta {
  43. return (*meta)(unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p)))
  44. }
  45. // leafPageElement retrieves the leaf node by index
  46. func (p *page) leafPageElement(index uint16) *leafPageElement {
  47. return (*leafPageElement)(unsafeIndex(unsafe.Pointer(p), unsafe.Sizeof(*p),
  48. leafPageElementSize, int(index)))
  49. }
  50. // leafPageElements retrieves a list of leaf nodes.
  51. func (p *page) leafPageElements() []leafPageElement {
  52. if p.count == 0 {
  53. return nil
  54. }
  55. var elems []leafPageElement
  56. data := unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p))
  57. unsafeSlice(unsafe.Pointer(&elems), data, int(p.count))
  58. return elems
  59. }
  60. // branchPageElement retrieves the branch node by index
  61. func (p *page) branchPageElement(index uint16) *branchPageElement {
  62. return (*branchPageElement)(unsafeIndex(unsafe.Pointer(p), unsafe.Sizeof(*p),
  63. unsafe.Sizeof(branchPageElement{}), int(index)))
  64. }
  65. // branchPageElements retrieves a list of branch nodes.
  66. func (p *page) branchPageElements() []branchPageElement {
  67. if p.count == 0 {
  68. return nil
  69. }
  70. var elems []branchPageElement
  71. data := unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p))
  72. unsafeSlice(unsafe.Pointer(&elems), data, int(p.count))
  73. return elems
  74. }
  75. // dump writes n bytes of the page to STDERR as hex output.
  76. func (p *page) hexdump(n int) {
  77. buf := unsafeByteSlice(unsafe.Pointer(p), 0, 0, n)
  78. fmt.Fprintf(os.Stderr, "%x\n", buf)
  79. }
  80. type pages []*page
  81. func (s pages) Len() int { return len(s) }
  82. func (s pages) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
  83. func (s pages) Less(i, j int) bool { return s[i].id < s[j].id }
  84. // branchPageElement represents a node on a branch page.
  85. type branchPageElement struct {
  86. pos uint32
  87. ksize uint32
  88. pgid pgid
  89. }
  90. // key returns a byte slice of the node key.
  91. func (n *branchPageElement) key() []byte {
  92. return unsafeByteSlice(unsafe.Pointer(n), 0, int(n.pos), int(n.pos)+int(n.ksize))
  93. }
  94. // leafPageElement represents a node on a leaf page.
  95. type leafPageElement struct {
  96. flags uint32
  97. pos uint32
  98. ksize uint32
  99. vsize uint32
  100. }
  101. // key returns a byte slice of the node key.
  102. func (n *leafPageElement) key() []byte {
  103. i := int(n.pos)
  104. j := i + int(n.ksize)
  105. return unsafeByteSlice(unsafe.Pointer(n), 0, i, j)
  106. }
  107. // value returns a byte slice of the node value.
  108. func (n *leafPageElement) value() []byte {
  109. i := int(n.pos) + int(n.ksize)
  110. j := i + int(n.vsize)
  111. return unsafeByteSlice(unsafe.Pointer(n), 0, i, j)
  112. }
  113. // PageInfo represents human readable information about a page.
  114. type PageInfo struct {
  115. ID int
  116. Type string
  117. Count int
  118. OverflowCount int
  119. }
  120. type pgids []pgid
  121. func (s pgids) Len() int { return len(s) }
  122. func (s pgids) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
  123. func (s pgids) Less(i, j int) bool { return s[i] < s[j] }
  124. // merge returns the sorted union of a and b.
  125. func (a pgids) merge(b pgids) pgids {
  126. // Return the opposite slice if one is nil.
  127. if len(a) == 0 {
  128. return b
  129. }
  130. if len(b) == 0 {
  131. return a
  132. }
  133. merged := make(pgids, len(a)+len(b))
  134. mergepgids(merged, a, b)
  135. return merged
  136. }
  137. // mergepgids copies the sorted union of a and b into dst.
  138. // If dst is too small, it panics.
  139. func mergepgids(dst, a, b pgids) {
  140. if len(dst) < len(a)+len(b) {
  141. panic(fmt.Errorf("mergepgids bad len %d < %d + %d", len(dst), len(a), len(b)))
  142. }
  143. // Copy in the opposite slice if one is nil.
  144. if len(a) == 0 {
  145. copy(dst, b)
  146. return
  147. }
  148. if len(b) == 0 {
  149. copy(dst, a)
  150. return
  151. }
  152. // Merged will hold all elements from both lists.
  153. merged := dst[:0]
  154. // Assign lead to the slice with a lower starting value, follow to the higher value.
  155. lead, follow := a, b
  156. if b[0] < a[0] {
  157. lead, follow = b, a
  158. }
  159. // Continue while there are elements in the lead.
  160. for len(lead) > 0 {
  161. // Merge largest prefix of lead that is ahead of follow[0].
  162. n := sort.Search(len(lead), func(i int) bool { return lead[i] > follow[0] })
  163. merged = append(merged, lead[:n]...)
  164. if n >= len(lead) {
  165. break
  166. }
  167. // Swap lead and follow.
  168. lead, follow = follow, lead[n:]
  169. }
  170. // Append what's left in follow.
  171. _ = append(merged, follow...)
  172. }