92 lines
2.1 KiB
Go
92 lines
2.1 KiB
Go
package internal
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
|
|
"github.com/tidwall/btree"
|
|
|
|
"cosmossdk.io/store/types"
|
|
)
|
|
|
|
const (
|
|
// The approximate number of items and children per B-tree node. Tuned with benchmarks.
|
|
// copied from memdb.
|
|
bTreeDegree = 32
|
|
)
|
|
|
|
var errKeyEmpty = errors.New("key cannot be empty")
|
|
|
|
// BTree implements the sorted cache for cachekv store,
|
|
// we don't use MemDB here because cachekv is used extensively in sdk core path,
|
|
// we need it to be as fast as possible, while `MemDB` is mainly used as a mocking db in unit tests.
|
|
//
|
|
// We choose tidwall/btree over google/btree here because it provides API to implement step iterator directly.
|
|
type BTree struct {
|
|
tree *btree.BTreeG[item]
|
|
}
|
|
|
|
// NewBTree creates a wrapper around `btree.BTreeG`.
|
|
func NewBTree() BTree {
|
|
return BTree{
|
|
tree: btree.NewBTreeGOptions(byKeys, btree.Options{
|
|
Degree: bTreeDegree,
|
|
NoLocks: false,
|
|
}),
|
|
}
|
|
}
|
|
|
|
func (bt BTree) Set(key, value []byte) {
|
|
bt.tree.Set(newItem(key, value))
|
|
}
|
|
|
|
func (bt BTree) Get(key []byte) []byte {
|
|
i, found := bt.tree.Get(newItem(key, nil))
|
|
if !found {
|
|
return nil
|
|
}
|
|
return i.value
|
|
}
|
|
|
|
func (bt BTree) Delete(key []byte) {
|
|
bt.tree.Delete(newItem(key, nil))
|
|
}
|
|
|
|
func (bt BTree) Iterator(start, end []byte) (types.Iterator, error) {
|
|
if (start != nil && len(start) == 0) || (end != nil && len(end) == 0) {
|
|
return nil, errKeyEmpty
|
|
}
|
|
return newMemIterator(start, end, bt, true), nil
|
|
}
|
|
|
|
func (bt BTree) ReverseIterator(start, end []byte) (types.Iterator, error) {
|
|
if (start != nil && len(start) == 0) || (end != nil && len(end) == 0) {
|
|
return nil, errKeyEmpty
|
|
}
|
|
return newMemIterator(start, end, bt, false), nil
|
|
}
|
|
|
|
// Copy the tree. This is a copy-on-write operation and is very fast because
|
|
// it only performs a shadowed copy.
|
|
func (bt BTree) Copy() BTree {
|
|
return BTree{
|
|
tree: bt.tree.Copy(),
|
|
}
|
|
}
|
|
|
|
// item is a btree item with byte slices as keys and values
|
|
type item struct {
|
|
key []byte
|
|
value []byte
|
|
}
|
|
|
|
// byKeys compares the items by key
|
|
func byKeys(a, b item) bool {
|
|
return bytes.Compare(a.key, b.key) == -1
|
|
}
|
|
|
|
// newItem creates a new pair item.
|
|
func newItem(key, value []byte) item {
|
|
return item{key: key, value: value}
|
|
}
|