github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/bitree/bdb/page.go (about) 1 // Copyright 2021 The Bitalosdb author(hustxrb@163.com) and other contributors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package bdb 16 17 import ( 18 "fmt" 19 "os" 20 "sort" 21 "unsafe" 22 23 "github.com/cockroachdb/errors" 24 ) 25 26 const pageHeaderSize = unsafe.Sizeof(page{}) 27 28 const minKeysPerPage = 2 29 30 const branchPageElementSize = unsafe.Sizeof(branchPageElement{}) 31 const leafPageElementSize = unsafe.Sizeof(leafPageElement{}) 32 33 const ( 34 branchPageFlag = 0x01 35 leafPageFlag = 0x02 36 metaPageFlag = 0x04 37 freelistPageFlag = 0x10 38 ) 39 40 const ( 41 bucketLeafFlag = 0x01 42 ) 43 44 type pgid uint64 45 46 type page struct { 47 id pgid 48 flags uint16 49 count uint16 50 overflow uint32 51 } 52 53 func (p *page) typ() string { 54 if (p.flags & branchPageFlag) != 0 { 55 return "branch" 56 } else if (p.flags & leafPageFlag) != 0 { 57 return "leaf" 58 } else if (p.flags & metaPageFlag) != 0 { 59 return "meta" 60 } else if (p.flags & freelistPageFlag) != 0 { 61 return "freelist" 62 } 63 return fmt.Sprintf("unknown<%02x>", p.flags) 64 } 65 66 func (p *page) meta() *meta { 67 return (*meta)(unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p))) 68 } 69 70 func (p *page) leafPageElement(index uint16) *leafPageElement { 71 return (*leafPageElement)(unsafeIndex(unsafe.Pointer(p), unsafe.Sizeof(*p), 72 leafPageElementSize, int(index))) 73 } 74 75 func (p *page) leafPageElements() []leafPageElement { 76 if p.count == 0 { 77 return nil 78 } 79 var elems []leafPageElement 80 data := unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p)) 81 unsafeSlice(unsafe.Pointer(&elems), data, int(p.count)) 82 return elems 83 } 84 85 func (p *page) branchPageElement(index uint16) *branchPageElement { 86 return (*branchPageElement)(unsafeIndex(unsafe.Pointer(p), unsafe.Sizeof(*p), 87 unsafe.Sizeof(branchPageElement{}), int(index))) 88 } 89 90 func (p *page) branchPageElements() []branchPageElement { 91 if p.count == 0 { 92 return nil 93 } 94 var elems []branchPageElement 95 data := unsafeAdd(unsafe.Pointer(p), unsafe.Sizeof(*p)) 96 unsafeSlice(unsafe.Pointer(&elems), data, int(p.count)) 97 return elems 98 } 99 100 func (p *page) hexdump(n int) { 101 buf := unsafeByteSlice(unsafe.Pointer(p), 0, 0, n) 102 fmt.Fprintf(os.Stderr, "%x\n", buf) 103 } 104 105 type pages []*page 106 107 func (s pages) Len() int { return len(s) } 108 func (s pages) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 109 func (s pages) Less(i, j int) bool { return s[i].id < s[j].id } 110 111 type branchPageElement struct { 112 pos uint32 113 ksize uint32 114 pgid pgid 115 } 116 117 func (n *branchPageElement) key() []byte { 118 return unsafeByteSlice(unsafe.Pointer(n), 0, int(n.pos), int(n.pos)+int(n.ksize)) 119 } 120 121 type leafPageElement struct { 122 flags uint32 123 pos uint32 124 ksize uint32 125 vsize uint32 126 } 127 128 func (n *leafPageElement) key() []byte { 129 i := int(n.pos) 130 j := i + int(n.ksize) 131 return unsafeByteSlice(unsafe.Pointer(n), 0, i, j) 132 } 133 134 func (n *leafPageElement) value() []byte { 135 i := int(n.pos) + int(n.ksize) 136 j := i + int(n.vsize) 137 return unsafeByteSlice(unsafe.Pointer(n), 0, i, j) 138 } 139 140 type PageInfo struct { 141 ID int 142 Type string 143 Count int 144 OverflowCount int 145 } 146 147 type pgids []pgid 148 149 func (s pgids) Len() int { return len(s) } 150 func (s pgids) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 151 func (s pgids) Less(i, j int) bool { return s[i] < s[j] } 152 153 func (a pgids) merge(b pgids) pgids { 154 if len(a) == 0 { 155 return b 156 } 157 if len(b) == 0 { 158 return a 159 } 160 merged := make(pgids, len(a)+len(b)) 161 mergepgids(merged, a, b) 162 return merged 163 } 164 165 func mergepgids(dst, a, b pgids) { 166 if len(dst) < len(a)+len(b) { 167 panic(errors.Errorf("mergepgids bad len %d < %d + %d", len(dst), len(a), len(b))) 168 } 169 170 if len(a) == 0 { 171 copy(dst, b) 172 return 173 } 174 if len(b) == 0 { 175 copy(dst, a) 176 return 177 } 178 179 merged := dst[:0] 180 181 lead, follow := a, b 182 if b[0] < a[0] { 183 lead, follow = b, a 184 } 185 186 for len(lead) > 0 { 187 n := sort.Search(len(lead), func(i int) bool { return lead[i] > follow[0] }) 188 merged = append(merged, lead[:n]...) 189 if n >= len(lead) { 190 break 191 } 192 193 lead, follow = follow, lead[n:] 194 } 195 196 _ = append(merged, follow...) 197 }