|
|
- package merkle
-
- const HASH_BYTE_SIZE int = 4 + 32
-
- /*
- Immutable AVL Tree (wraps the Node root)
-
- This tree is not concurrency safe.
- You must wrap your calls with your own mutex.
- */
- type IAVLTree struct {
- db Db
- root *IAVLNode
- }
-
- func NewIAVLTree(db Db) *IAVLTree {
- return &IAVLTree{
- db: db,
- root: nil,
- }
- }
-
- // TODO rename to Load.
- func NewIAVLTreeFromHash(db Db, hash []byte) *IAVLTree {
- root := &IAVLNode{
- hash: hash,
- flags: IAVLNODE_FLAG_PERSISTED | IAVLNODE_FLAG_PLACEHOLDER,
- }
- root.fill(db)
- return &IAVLTree{db: db, root: root}
- }
-
- func NewIAVLTreeFromKey(db Db, key string) *IAVLTree {
- hash := db.Get([]byte(key))
- if hash == nil {
- return nil
- }
- root := &IAVLNode{
- hash: hash,
- flags: IAVLNODE_FLAG_PERSISTED | IAVLNODE_FLAG_PLACEHOLDER,
- }
- root.fill(db)
- return &IAVLTree{db: db, root: root}
- }
-
- func (t *IAVLTree) Size() uint64 {
- if t.root == nil {
- return 0
- }
- return t.root.Size()
- }
-
- func (t *IAVLTree) Height() uint8 {
- if t.root == nil {
- return 0
- }
- return t.root.Height()
- }
-
- func (t *IAVLTree) Has(key []byte) bool {
- if t.root == nil {
- return false
- }
- return t.root.has(t.db, key)
- }
-
- func (t *IAVLTree) Set(key []byte, value []byte) (updated bool) {
- if t.root == nil {
- t.root = NewIAVLNode(key, value)
- return false
- }
- t.root, updated = t.root.set(t.db, key, value)
- return updated
- }
-
- func (t *IAVLTree) Hash() []byte {
- if t.root == nil {
- return nil
- }
- hash, _ := t.root.HashWithCount()
- return hash
- }
-
- func (t *IAVLTree) HashWithCount() ([]byte, uint64) {
- if t.root == nil {
- return nil, 0
- }
- return t.root.HashWithCount()
- }
-
- func (t *IAVLTree) Save() {
- if t.root == nil {
- return
- }
- t.root.HashWithCount()
- t.root.Save(t.db)
- }
-
- func (t *IAVLTree) SaveKey(key string) {
- if t.root == nil {
- return
- }
- hash, _ := t.root.HashWithCount()
- t.root.Save(t.db)
- t.db.Set([]byte(key), hash)
- }
-
- func (t *IAVLTree) Get(key []byte) (value []byte) {
- if t.root == nil {
- return nil
- }
- return t.root.get(t.db, key)
- }
-
- func (t *IAVLTree) Remove(key []byte) (value []byte, err error) {
- if t.root == nil {
- return nil, NotFound(key)
- }
- newRoot, _, value, err := t.root.remove(t.db, key)
- if err != nil {
- return nil, err
- }
- t.root = newRoot
- return value, nil
- }
-
- func (t *IAVLTree) Copy() Tree {
- return &IAVLTree{db: t.db, root: t.root}
- }
|