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  }