page.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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. func (p *page) fastCheck(id pgid) {
  46. _assert(p.id == id, "Page expected to be: %v, but self identifies as %v", id, p.id)
  47. // Only one flag of page-type can be set.
  48. _assert(p.flags == branchPageFlag ||
  49. p.flags == leafPageFlag ||
  50. p.flags == metaPageFlag ||
  51. p.flags == freelistPageFlag,
  52. "page %v: has unexpected type/flags: %x", p.id, p.flags)
  53. }
  54. // leafPageElement retrieves the leaf node by index
  55. func (p *page) leafPageElement(index uint16) *leafPageElement {
  56. return (*leafPageElement)(unsafeIndex(unsafe.Pointer(p), unsafe.Sizeof(*p),
  57. leafPageElementSize, int(index)))
  58. }
  59. // leafPageElements retrieves a list of leaf nodes.
  60. func (p *page) leafPageElements() []leafPageElement {
  61. if p.count == 0 {
  62. return nil
  63. }
  64. var elems []leafPageElement
  65. data := unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p))
  66. unsafeSlice(unsafe.Pointer(&elems), data, int(p.count))
  67. return elems
  68. }
  69. // branchPageElement retrieves the branch node by index
  70. func (p *page) branchPageElement(index uint16) *branchPageElement {
  71. return (*branchPageElement)(unsafeIndex(unsafe.Pointer(p), unsafe.Sizeof(*p),
  72. unsafe.Sizeof(branchPageElement{}), int(index)))
  73. }
  74. // branchPageElements retrieves a list of branch nodes.
  75. func (p *page) branchPageElements() []branchPageElement {
  76. if p.count == 0 {
  77. return nil
  78. }
  79. var elems []branchPageElement
  80. data := unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p))
  81. unsafeSlice(unsafe.Pointer(&elems), data, int(p.count))
  82. return elems
  83. }
  84. // dump writes n bytes of the page to STDERR as hex output.
  85. func (p *page) hexdump(n int) {
  86. buf := unsafeByteSlice(unsafe.Pointer(p), 0, 0, n)
  87. fmt.Fprintf(os.Stderr, "%x\n", buf)
  88. }
  89. type pages []*page
  90. func (s pages) Len() int { return len(s) }
  91. func (s pages) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
  92. func (s pages) Less(i, j int) bool { return s[i].id < s[j].id }
  93. // branchPageElement represents a node on a branch page.
  94. type branchPageElement struct {
  95. pos uint32
  96. ksize uint32
  97. pgid pgid
  98. }
  99. // key returns a byte slice of the node key.
  100. func (n *branchPageElement) key() []byte {
  101. return unsafeByteSlice(unsafe.Pointer(n), 0, int(n.pos), int(n.pos)+int(n.ksize))
  102. }
  103. // leafPageElement represents a node on a leaf page.
  104. type leafPageElement struct {
  105. flags uint32
  106. pos uint32
  107. ksize uint32
  108. vsize uint32
  109. }
  110. // key returns a byte slice of the node key.
  111. func (n *leafPageElement) key() []byte {
  112. i := int(n.pos)
  113. j := i + int(n.ksize)
  114. return unsafeByteSlice(unsafe.Pointer(n), 0, i, j)
  115. }
  116. // value returns a byte slice of the node value.
  117. func (n *leafPageElement) value() []byte {
  118. i := int(n.pos) + int(n.ksize)
  119. j := i + int(n.vsize)
  120. return unsafeByteSlice(unsafe.Pointer(n), 0, i, j)
  121. }
  122. // PageInfo represents human readable information about a page.
  123. type PageInfo struct {
  124. ID int
  125. Type string
  126. Count int
  127. OverflowCount int
  128. }
  129. type pgids []pgid
  130. func (s pgids) Len() int { return len(s) }
  131. func (s pgids) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
  132. func (s pgids) Less(i, j int) bool { return s[i] < s[j] }
  133. // merge returns the sorted union of a and b.
  134. func (a pgids) merge(b pgids) pgids {
  135. // Return the opposite slice if one is nil.
  136. if len(a) == 0 {
  137. return b
  138. }
  139. if len(b) == 0 {
  140. return a
  141. }
  142. merged := make(pgids, len(a)+len(b))
  143. mergepgids(merged, a, b)
  144. return merged
  145. }
  146. // mergepgids copies the sorted union of a and b into dst.
  147. // If dst is too small, it panics.
  148. func mergepgids(dst, a, b pgids) {
  149. if len(dst) < len(a)+len(b) {
  150. panic(fmt.Errorf("mergepgids bad len %d < %d + %d", len(dst), len(a), len(b)))
  151. }
  152. // Copy in the opposite slice if one is nil.
  153. if len(a) == 0 {
  154. copy(dst, b)
  155. return
  156. }
  157. if len(b) == 0 {
  158. copy(dst, a)
  159. return
  160. }
  161. // Merged will hold all elements from both lists.
  162. merged := dst[:0]
  163. // Assign lead to the slice with a lower starting value, follow to the higher value.
  164. lead, follow := a, b
  165. if b[0] < a[0] {
  166. lead, follow = b, a
  167. }
  168. // Continue while there are elements in the lead.
  169. for len(lead) > 0 {
  170. // Merge largest prefix of lead that is ahead of follow[0].
  171. n := sort.Search(len(lead), func(i int) bool { return lead[i] > follow[0] })
  172. merged = append(merged, lead[:n]...)
  173. if n >= len(lead) {
  174. break
  175. }
  176. // Swap lead and follow.
  177. lead, follow = follow, lead[n:]
  178. }
  179. // Append what's left in follow.
  180. _ = append(merged, follow...)
  181. }