Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
catShaark committed Oct 4, 2022
1 parent 2f72b90 commit 5924e7e
Show file tree
Hide file tree
Showing 17 changed files with 381 additions and 273 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ jobs:
- name: test & coverage report creation
run: |
go test ./... -mod=readonly -timeout 5m -short -race -coverprofile=coverage.txt -covermode=atomic
go test ./... -mod=readonly -timeout 8m
GOARCH=386 go test ./... -mod=readonly -timeout 8m
go test ./... -mod=readonly -timeout 5m
GOARCH=386 go test ./... -mod=readonly -timeout 5m
5 changes: 3 additions & 2 deletions basic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ func TestPersistence(t *testing.T) {

// Create some random key value pairs
records := make(map[string]string)
for i := 0; i < 10000; i++ {
for i := 0; i < 8; i++ {
records[randstr(20)] = randstr(20)
}

Expand All @@ -480,7 +480,8 @@ func TestPersistence(t *testing.T) {
// Load a tree
t2, err := NewMutableTree(db, 0, false)
require.NoError(t, err)
t2.Load()
_, err = t2.Load()
require.NoError(t, err)
for key, value := range records {
t2value, err := t2.Get([]byte(key))
require.NoError(t, err)
Expand Down
4 changes: 2 additions & 2 deletions docs/tree/mutable_tree.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,9 @@ Before `RotateRight(node8)`:
After `RotateRight(node8)`:
```
|---9
|---8
|---8 call SaveNode(*node)
| | |---7
| |---6
| |---6(P)
| |---5
4'---|
| |---1
Expand Down
25 changes: 25 additions & 0 deletions export_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package iavl

import (
"fmt"
"math"
"math/rand"
"testing"
Expand All @@ -11,6 +12,25 @@ import (
db "github.com/cosmos/cosmos-db"
)

func printNodes(t *MutableTree) {
actual := []ExportNode{}
exporter := t.Export()
defer exporter.Close()
for {
node, err := exporter.Next()
if err == ExportDone {
break
}
actual = append(actual, *node)
}

for _, i := range actual {
fmt.Printf("Key: %s, Value: %d, Version: %d, Height: %d \n", i.Key, i.Value, i.Version, i.Height)
}

fmt.Println("==================")
}

// setupExportTreeBasic sets up a basic tree with a handful of
// create/update/delete operations over a few versions.
func setupExportTreeBasic(t require.TestingT) *ImmutableTree {
Expand Down Expand Up @@ -172,6 +192,11 @@ func TestExporter(t *testing.T) {
}

assert.Equal(t, expect, actual)
// fmt.Println(tree.RenderShape(" ", defaultNodeEncoder))

// for _, i := range actual {
// fmt.Printf("Key: %s, Value: %d, Version: %d, Height: %d \n", i.Key, i.Value, i.Version, i.Height)
// }
}

func TestExporter_Import(t *testing.T) {
Expand Down
18 changes: 9 additions & 9 deletions immutable_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,15 @@ func (t *ImmutableTree) renderNode(node *Node, indent string, depth int, encoder
// recurse on inner node
here := fmt.Sprintf("%s%s", prefix, encoder(node.hash, depth, false))

rightNode, err := node.getRightNode(t)
if err != nil {
return nil, err
}

leftNode, err := node.getLeftNode(t)
if err != nil {
return nil, err
}
rightNode := node.rightNode
// if err != nil {
// return nil, err
// }

leftNode := node.leftNode
// if err != nil {
// return nil, err
// }

right, err := t.renderNode(rightNode, indent, depth+1, encoder)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion import.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func (i *Importer) Add(exportNode *ExportNode) error {
bytesCopy := make([]byte, buf.Len())
copy(bytesCopy, buf.Bytes())

if err = i.batch.Set(i.tree.ndb.nodeKey(node.GetKey()), bytesCopy); err != nil {
if err = i.batch.Set(node.GetKey(), bytesCopy); err != nil {
return err
}

Expand Down
6 changes: 6 additions & 0 deletions keyformat/key_format.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,19 @@ func format(a interface{}) []byte {
return formatUint64(uint64(v))
case int:
return formatUint64(uint64(v))
case uint8:
return formatUint8(v)
case []byte:
return v
default:
panic(fmt.Errorf("keyFormat format() does not support formatting value of type %T: %v", a, a))
}
}

func formatUint8(v uint8) []byte {
return []byte{v}
}

func formatUint64(v uint64) []byte {
bs := make([]byte, 8)
binary.BigEndian.PutUint64(bs, v)
Expand Down
83 changes: 50 additions & 33 deletions mutable_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ type MutableTree struct {
mtx sync.Mutex
}

func NewRootNodeKeyWithVersion(version int64) []byte {
return nodeKeyFormat.Key(version, make([]byte, 9))
}

// NewMutableTree returns a new tree with the specified cache size and datastore.
func NewMutableTree(db dbm.DB, cacheSize int, skipFastStorageUpgrade bool) (*MutableTree, error) {
return NewMutableTreeWithOpts(db, cacheSize, nil, skipFastStorageUpgrade)
Expand Down Expand Up @@ -339,7 +343,7 @@ func (tree *MutableTree) remove(key []byte) (value []byte, orphaned []*Node, rem
return nil, nil, false, nil
}
orphaned = tree.prepareOrphansSlice()
newRootHash, newRoot, _, value, err := tree.recursiveRemove(tree.root, key, &orphaned)
newRootHash, _, newRoot, _, value, err := tree.recursiveRemove(tree.root, key, &orphaned)
if err != nil {
return nil, nil, false, err
}
Expand All @@ -350,10 +354,12 @@ func (tree *MutableTree) remove(key []byte) (value []byte, orphaned []*Node, rem
tree.addUnsavedRemoval(key)

if newRoot == nil && newRootHash != nil {
tree.root, err = tree.ndb.GetNode(newRootHash)
nodeKey := NewRootNodeKeyWithVersion(tree.version + 1) // tree.version + 1 == tree.root.version
tree.root, err = tree.ndb.GetNode(nodeKey)
if err != nil {
return nil, nil, false, err
}
tree.root.hash = newRootHash
} else {
tree.root = newRoot
}
Expand All @@ -367,90 +373,92 @@ func (tree *MutableTree) remove(key []byte) (value []byte, orphaned []*Node, rem
// - new leftmost leaf key for tree after successfully removing 'key' if changed.
// - the removed value
// - the orphaned nodes.
func (tree *MutableTree) recursiveRemove(node *Node, key []byte, orphans *[]*Node) (newHash []byte, newSelf *Node, newKey []byte, newValue []byte, err error) {
func (tree *MutableTree) recursiveRemove(node *Node, key []byte, orphans *[]*Node) (newHash []byte, newNodeKey []byte, newSelf *Node, newKey []byte, value []byte, err error) {
version := tree.version + 1

if node.isLeaf() {
if bytes.Equal(key, node.key) {
*orphans = append(*orphans, node)
return nil, nil, nil, node.value, nil
return nil, nil, nil, nil, node.value, nil
}
return node.hash, node, nil, nil, nil
return node.hash, node.nodeKey, node, nil, nil, nil
}

// node.key < key; we go to the left to find the key:
if bytes.Compare(key, node.key) < 0 {
leftNode, err := node.getLeftNode(tree.ImmutableTree)
if err != nil {
return nil, nil, nil, nil, err
return nil, nil, nil, nil, nil, err
}
newLeftHash, newLeftNode, newKey, value, err := tree.recursiveRemove(leftNode, key, orphans)
newLeftHash, newLeftNodeKey, newLeftNode, newKey, value, err := tree.recursiveRemove(leftNode, key, orphans)
if err != nil {
return nil, nil, nil, nil, err
return nil, nil, nil, nil, nil, err
}

// if the node removed is not in this branch
if len(*orphans) == 0 {
return node.hash, node, nil, value, nil
return node.hash, node.nodeKey, node, nil, nil, nil
}
*orphans = append(*orphans, node)
if newLeftHash == nil && newLeftNode == nil { // left node held value, was removed
return node.rightHash, node.rightNode, node.key, value, nil
// this node become exactly its right node if
return node.rightHash, node.rightChildNodeKey, node.rightNode, node.key, value, nil
}

newNode, err := node.clone(version)
if err != nil {
return nil, nil, nil, nil, err
return nil, nil, nil, nil, nil, err
}

newNode.leftHash, newNode.leftNode = newLeftHash, newLeftNode
newNode.leftHash, newNode.leftNode, newNode.leftChildNodeKey = newLeftHash, newLeftNode, newLeftNodeKey
err = newNode.calcHeightAndSize(tree.ImmutableTree)
if err != nil {
return nil, nil, nil, nil, err
return nil, nil, nil, nil, nil, err
}
newNode, err = tree.balance(newNode, orphans)
if err != nil {
return nil, nil, nil, nil, err
return nil, nil, nil, nil, nil, err
}

return newNode.hash, newNode, newKey, value, nil
return newNode.hash, newNode.nodeKey, newNode, newKey, value, nil
}
// node.key >= key; either found or look to the right:
rightNode, err := node.getRightNode(tree.ImmutableTree)
if err != nil {
return nil, nil, nil, nil, err
return nil, nil, nil, nil, nil, err
}
newRightHash, newRightNode, newKey, value, err := tree.recursiveRemove(rightNode, key, orphans)
newRightHash, newRightNodeKey, newRightNode, newKey, value, err := tree.recursiveRemove(rightNode, key, orphans)
if err != nil {
return nil, nil, nil, nil, err
return nil, nil, nil, nil, nil, err
}
if len(*orphans) == 0 {
return node.hash, node, nil, value, nil
return node.hash, node.nodeKey, node, nil, value, nil
}
*orphans = append(*orphans, node)
if newRightHash == nil && newRightNode == nil { // right node held value, was removed
return node.leftHash, node.leftNode, nil, value, nil
return node.leftHash, node.leftChildNodeKey, node.leftNode, nil, value, nil
}

newNode, err := node.clone(version)
if err != nil {
return nil, nil, nil, nil, err
return nil, nil, nil, nil, nil, err
}

newNode.rightHash, newNode.rightNode = newRightHash, newRightNode
newNode.rightHash, newNode.rightNode, newNode.rightChildNodeKey = newRightHash, newRightNode, newRightNodeKey
if newKey != nil {
newNode.key = newKey
}
err = newNode.calcHeightAndSize(tree.ImmutableTree)
if err != nil {
return nil, nil, nil, nil, err
return nil, nil, nil, nil, nil, err
}

newNode, err = tree.balance(newNode, orphans)
if err != nil {
return nil, nil, nil, nil, err
return nil, nil, nil, nil, nil, err
}

return newNode.hash, newNode, nil, value, nil
return newNode.hash, newNode.nodeKey, newNode, nil, value, nil
}

// Load the latest versioned tree from disk.
Expand Down Expand Up @@ -514,10 +522,12 @@ func (tree *MutableTree) LazyLoadVersion(targetVersion int64) (int64, error) {
if len(rootHash) > 0 {
// If rootHash is empty then root of tree should be nil
// This makes `LazyLoadVersion` to do the same thing as `LoadVersion`
iTree.root, err = tree.ndb.GetNode(rootHash)
nodeKey := NewRootNodeKeyWithVersion(targetVersion)
iTree.root, err = tree.ndb.GetNode(nodeKey)
if err != nil {
return 0, err
}
iTree.root.hash = rootHash
}

tree.orphans = map[string]int64{}
Expand Down Expand Up @@ -589,10 +599,12 @@ func (tree *MutableTree) LoadVersion(targetVersion int64) (int64, error) {
}

if len(latestRoot) != 0 {
t.root, err = tree.ndb.GetNode(latestRoot)
nodeKey := NewRootNodeKeyWithVersion(latestVersion)
t.root, err = tree.ndb.GetNode(nodeKey)
if err != nil {
return 0, err
}
t.root.hash = latestRoot
}

tree.orphans = map[string]int64{}
Expand Down Expand Up @@ -754,10 +766,13 @@ func (tree *MutableTree) GetImmutable(version int64) (*ImmutableTree, error) {
}
tree.versions[version] = true

root, err := tree.ndb.GetNode(rootHash)
nodeKey := NewRootNodeKeyWithVersion(version)
root, err := tree.ndb.GetNode(nodeKey)
if err != nil {
return nil, err
}
root.hash = rootHash

return &ImmutableTree{
root: root,
ndb: tree.ndb,
Expand Down Expand Up @@ -869,7 +884,7 @@ func (tree *MutableTree) SaveVersion() ([]byte, int64, error) {
}
} else {
logger.Debug("SAVE TREE %v\n", version)
if _, err := tree.ndb.SaveBranch(tree.root); err != nil {
if _, _, err := tree.ndb.SaveBranch(tree.root); err != nil {
return nil, 0, err
}
if err := tree.ndb.SaveOrphans(version, tree.orphans); err != nil {
Expand Down Expand Up @@ -1077,6 +1092,7 @@ func (tree *MutableTree) rotateRight(node *Node) (*Node, *Node, error) {

var err error
// TODO: optimize balance & rotate.
// node that rotateRight
node, err = node.clone(version)
if err != nil {
return nil, nil, err
Expand All @@ -1086,14 +1102,15 @@ func (tree *MutableTree) rotateRight(node *Node) (*Node, *Node, error) {
if err != nil {
return nil, nil, err
}
// node that got removed
newNode, err := orphaned.clone(version)
if err != nil {
return nil, nil, err
}

newNoderHash, newNoderCached := newNode.rightHash, newNode.rightNode
newNoderHash, newNoderCached, newNodeRightChildNodeKey := newNode.rightHash, newNode.rightNode, newNode.rightChildNodeKey
newNode.rightHash, newNode.rightNode = node.hash, node
node.leftHash, node.leftNode = newNoderHash, newNoderCached
node.leftHash, node.leftNode, node.leftChildNodeKey = newNoderHash, newNoderCached, newNodeRightChildNodeKey

err = node.calcHeightAndSize(tree.ImmutableTree)
if err != nil {
Expand Down Expand Up @@ -1128,9 +1145,9 @@ func (tree *MutableTree) rotateLeft(node *Node) (*Node, *Node, error) {
return nil, nil, err
}

newNodelHash, newNodelCached := newNode.leftHash, newNode.leftNode
newNodelHash, newNodelCached, newNodeLeftChildNodeKey := newNode.leftHash, newNode.leftNode, newNode.leftChildNodeKey
newNode.leftHash, newNode.leftNode = node.hash, node
node.rightHash, node.rightNode = newNodelHash, newNodelCached
node.rightHash, node.rightNode, node.rightChildNodeKey = newNodelHash, newNodelCached, newNodeLeftChildNodeKey

err = node.calcHeightAndSize(tree.ImmutableTree)
if err != nil {
Expand Down
Loading

0 comments on commit 5924e7e

Please sign in to comment.