github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/bitree/bdb/cursor.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 "bytes" 19 "fmt" 20 "sort" 21 ) 22 23 type Cursor struct { 24 bucket *Bucket 25 stack []elemRef 26 } 27 28 func (c *Cursor) Bucket() *Bucket { 29 return c.bucket 30 } 31 32 func (c *Cursor) First() (key []byte, value []byte) { 33 _assert(c.bucket.tx.db != nil, "tx closed") 34 c.stack = c.stack[:0] 35 p, n := c.bucket.pageNode(c.bucket.root) 36 c.stack = append(c.stack, elemRef{page: p, node: n, index: 0}) 37 c.first() 38 39 if c.stack[len(c.stack)-1].count() == 0 { 40 c.next() 41 } 42 43 k, v, flags := c.keyValue() 44 if (flags & uint32(bucketLeafFlag)) != 0 { 45 return k, nil 46 } 47 return k, v 48 } 49 50 func (c *Cursor) Last() (key []byte, value []byte) { 51 _assert(c.bucket.tx.db != nil, "tx closed") 52 c.stack = c.stack[:0] 53 p, n := c.bucket.pageNode(c.bucket.root) 54 ref := elemRef{page: p, node: n} 55 ref.index = ref.count() - 1 56 c.stack = append(c.stack, ref) 57 c.last() 58 k, v, flags := c.keyValue() 59 if (flags & uint32(bucketLeafFlag)) != 0 { 60 return k, nil 61 } 62 return k, v 63 } 64 65 func (c *Cursor) Next() (key []byte, value []byte) { 66 _assert(c.bucket.tx.db != nil, "tx closed") 67 k, v, flags := c.next() 68 if (flags & uint32(bucketLeafFlag)) != 0 { 69 return k, nil 70 } 71 return k, v 72 } 73 74 func (c *Cursor) Prev() (key []byte, value []byte) { 75 _assert(c.bucket.tx.db != nil, "tx closed") 76 77 for i := len(c.stack) - 1; i >= 0; i-- { 78 elem := &c.stack[i] 79 if elem.index > 0 { 80 elem.index-- 81 break 82 } 83 c.stack = c.stack[:i] 84 } 85 86 if len(c.stack) == 0 { 87 return nil, nil 88 } 89 90 c.last() 91 k, v, flags := c.keyValue() 92 if (flags & uint32(bucketLeafFlag)) != 0 { 93 return k, nil 94 } 95 return k, v 96 } 97 98 func (c *Cursor) Seek(seek []byte) (key []byte, value []byte) { 99 k, v, flags := c.seek(seek) 100 101 if ref := &c.stack[len(c.stack)-1]; ref.index >= ref.count() { 102 k, v, flags = c.next() 103 } 104 105 if k == nil { 106 return nil, nil 107 } else if (flags & uint32(bucketLeafFlag)) != 0 { 108 return k, nil 109 } 110 return k, v 111 } 112 113 func (c *Cursor) Delete() error { 114 if c.bucket.tx.db == nil { 115 return ErrTxClosed 116 } else if !c.bucket.Writable() { 117 return ErrTxNotWritable 118 } 119 120 key, _, flags := c.keyValue() 121 if (flags & bucketLeafFlag) != 0 { 122 return ErrIncompatibleValue 123 } 124 c.node().del(key) 125 126 return nil 127 } 128 129 func (c *Cursor) seek(seek []byte) (key []byte, value []byte, flags uint32) { 130 _assert(c.bucket.tx.db != nil, "tx closed") 131 132 c.stack = c.stack[:0] 133 c.search(seek, c.bucket.root) 134 135 return c.keyValue() 136 } 137 138 func (c *Cursor) first() { 139 for { 140 var ref = &c.stack[len(c.stack)-1] 141 if ref.isLeaf() { 142 break 143 } 144 145 var pgid pgid 146 if ref.node != nil { 147 pgid = ref.node.inodes[ref.index].pgid 148 } else { 149 pgid = ref.page.branchPageElement(uint16(ref.index)).pgid 150 } 151 p, n := c.bucket.pageNode(pgid) 152 c.stack = append(c.stack, elemRef{page: p, node: n, index: 0}) 153 } 154 } 155 156 func (c *Cursor) last() { 157 for { 158 ref := &c.stack[len(c.stack)-1] 159 if ref.isLeaf() { 160 break 161 } 162 163 var pgid pgid 164 if ref.node != nil { 165 pgid = ref.node.inodes[ref.index].pgid 166 } else { 167 pgid = ref.page.branchPageElement(uint16(ref.index)).pgid 168 } 169 p, n := c.bucket.pageNode(pgid) 170 171 var nextRef = elemRef{page: p, node: n} 172 nextRef.index = nextRef.count() - 1 173 c.stack = append(c.stack, nextRef) 174 } 175 } 176 177 func (c *Cursor) next() (key []byte, value []byte, flags uint32) { 178 for { 179 var i int 180 for i = len(c.stack) - 1; i >= 0; i-- { 181 elem := &c.stack[i] 182 if elem.index < elem.count()-1 { 183 elem.index++ 184 break 185 } 186 } 187 188 if i == -1 { 189 return nil, nil, 0 190 } 191 192 c.stack = c.stack[:i+1] 193 c.first() 194 195 if c.stack[len(c.stack)-1].count() == 0 { 196 continue 197 } 198 199 return c.keyValue() 200 } 201 } 202 203 func (c *Cursor) search(key []byte, pgid pgid) { 204 p, n := c.bucket.pageNode(pgid) 205 if p != nil && (p.flags&(branchPageFlag|leafPageFlag)) == 0 { 206 panic(fmt.Sprintf("invalid page type: %d: %x", p.id, p.flags)) 207 } 208 e := elemRef{page: p, node: n} 209 c.stack = append(c.stack, e) 210 211 if e.isLeaf() { 212 c.nsearch(key) 213 return 214 } 215 216 if n != nil { 217 c.searchNode(key, n) 218 return 219 } 220 c.searchPage(key, p) 221 } 222 223 func (c *Cursor) searchNode(key []byte, n *node) { 224 var exact bool 225 index := sort.Search(len(n.inodes), func(i int) bool { 226 ret := bytes.Compare(n.inodes[i].key, key) 227 if ret == 0 { 228 exact = true 229 } 230 return ret != -1 231 }) 232 if !exact && index > 0 { 233 index-- 234 } 235 c.stack[len(c.stack)-1].index = index 236 237 c.search(key, n.inodes[index].pgid) 238 } 239 240 func (c *Cursor) searchPage(key []byte, p *page) { 241 inodes := p.branchPageElements() 242 243 var exact bool 244 index := sort.Search(int(p.count), func(i int) bool { 245 ret := bytes.Compare(inodes[i].key(), key) 246 if ret == 0 { 247 exact = true 248 } 249 return ret != -1 250 }) 251 if !exact && index > 0 { 252 index-- 253 } 254 c.stack[len(c.stack)-1].index = index 255 256 c.search(key, inodes[index].pgid) 257 } 258 259 func (c *Cursor) nsearch(key []byte) { 260 e := &c.stack[len(c.stack)-1] 261 p, n := e.page, e.node 262 263 if n != nil { 264 index := sort.Search(len(n.inodes), func(i int) bool { 265 return bytes.Compare(n.inodes[i].key, key) != -1 266 }) 267 e.index = index 268 return 269 } 270 271 inodes := p.leafPageElements() 272 index := sort.Search(int(p.count), func(i int) bool { 273 return bytes.Compare(inodes[i].key(), key) != -1 274 }) 275 e.index = index 276 } 277 278 func (c *Cursor) keyValue() ([]byte, []byte, uint32) { 279 ref := &c.stack[len(c.stack)-1] 280 281 if ref.count() == 0 || ref.index >= ref.count() { 282 return nil, nil, 0 283 } 284 285 if ref.node != nil { 286 inode := &ref.node.inodes[ref.index] 287 return inode.key, inode.value, inode.flags 288 } 289 290 elem := ref.page.leafPageElement(uint16(ref.index)) 291 return elem.key(), elem.value(), elem.flags 292 } 293 294 func (c *Cursor) node() *node { 295 _assert(len(c.stack) > 0, "accessing a node with a zero-length cursor stack") 296 297 if ref := &c.stack[len(c.stack)-1]; ref.node != nil && ref.isLeaf() { 298 return ref.node 299 } 300 301 var n = c.stack[0].node 302 if n == nil { 303 n = c.bucket.node(c.stack[0].page.id, nil) 304 } 305 for _, ref := range c.stack[:len(c.stack)-1] { 306 _assert(!n.isLeaf, "expected branch node") 307 n = n.childAt(ref.index) 308 } 309 _assert(n.isLeaf, "expected leaf node") 310 return n 311 } 312 313 type elemRef struct { 314 page *page 315 node *node 316 index int 317 } 318 319 func (r *elemRef) isLeaf() bool { 320 if r.node != nil { 321 return r.node.isLeaf 322 } 323 return (r.page.flags & leafPageFlag) != 0 324 } 325 326 func (r *elemRef) count() int { 327 if r.node != nil { 328 return len(r.node.inodes) 329 } 330 return int(r.page.count) 331 }