Skip to content

Commit

Permalink
Clone w/ version; Remove orphanIndex
Browse files Browse the repository at this point in the history
  • Loading branch information
jaekwon committed Dec 9, 2017
1 parent 016c487 commit 8ffd5bf
Show file tree
Hide file tree
Showing 11 changed files with 191 additions and 254 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
vendor
.glide
*.swp
*.swo

# created in test code
test.db
Expand Down
22 changes: 11 additions & 11 deletions basic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func TestBasic(t *testing.T) {

// Test 0x00
{
idx, val := tree.Get([]byte{0x00})
idx, val := tree.Get64([]byte{0x00})
if val != nil {
t.Errorf("Expected no value to exist")
}
Expand All @@ -46,7 +46,7 @@ func TestBasic(t *testing.T) {

// Test "1"
{
idx, val := tree.Get([]byte("1"))
idx, val := tree.Get64([]byte("1"))
if val == nil {
t.Errorf("Expected value to exist")
}
Expand All @@ -60,7 +60,7 @@ func TestBasic(t *testing.T) {

// Test "2"
{
idx, val := tree.Get([]byte("2"))
idx, val := tree.Get64([]byte("2"))
if val == nil {
t.Errorf("Expected value to exist")
}
Expand All @@ -74,7 +74,7 @@ func TestBasic(t *testing.T) {

// Test "4"
{
idx, val := tree.Get([]byte("4"))
idx, val := tree.Get64([]byte("4"))
if val != nil {
t.Errorf("Expected no value to exist")
}
Expand All @@ -88,7 +88,7 @@ func TestBasic(t *testing.T) {

// Test "6"
{
idx, val := tree.Get([]byte("6"))
idx, val := tree.Get64([]byte("6"))
if val != nil {
t.Errorf("Expected no value to exist")
}
Expand All @@ -103,7 +103,7 @@ func TestBasic(t *testing.T) {

func TestUnit(t *testing.T) {

expectHash := func(tree *Tree, hashCount int) {
expectHash := func(tree *Tree, hashCount int64) {
// ensure number of new hash calculations is as expected.
hash, count := tree.hashWithCount()
if count != hashCount {
Expand All @@ -121,7 +121,7 @@ func TestUnit(t *testing.T) {
}
}

expectSet := func(tree *Tree, i int, repr string, hashCount int) {
expectSet := func(tree *Tree, i int, repr string, hashCount int64) {
origNode := tree.root
updated := tree.Set(i2b(i), []byte{})
// ensure node was added & structure is as expected.
Expand All @@ -134,7 +134,7 @@ func TestUnit(t *testing.T) {
tree.root = origNode
}

expectRemove := func(tree *Tree, i int, repr string, hashCount int) {
expectRemove := func(tree *Tree, i int, repr string, hashCount int64) {
origNode := tree.root
value, removed := tree.Remove(i2b(i))
// ensure node was added & structure is as expected.
Expand Down Expand Up @@ -249,7 +249,7 @@ func TestIntegration(t *testing.T) {
if has := tree.Has([]byte(randstr(12))); has {
t.Error("Table has extra key")
}
if _, val := tree.Get([]byte(r.key)); string(val) != string(r.value) {
if _, val := tree.Get64([]byte(r.key)); string(val) != string(r.value) {
t.Error("wrong value")
}
}
Expand All @@ -267,7 +267,7 @@ func TestIntegration(t *testing.T) {
if has := tree.Has([]byte(randstr(12))); has {
t.Error("Table has extra key")
}
_, val := tree.Get([]byte(r.key))
_, val := tree.Get64([]byte(r.key))
if string(val) != string(r.value) {
t.Error("wrong value")
}
Expand Down Expand Up @@ -379,7 +379,7 @@ func TestPersistence(t *testing.T) {
t2 := NewVersionedTree(0, db)
t2.Load()
for key, value := range records {
_, t2value := t2.Get([]byte(key))
_, t2value := t2.Get64([]byte(key))
if string(t2value) != value {
t.Fatalf("Invalid value. Expected %v, got %v", value, t2value)
}
Expand Down
11 changes: 11 additions & 0 deletions logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package iavl

import (
"fmt"
)

func debug(format string, args ...interface{}) {
if false {
fmt.Printf(format, args...)
}
}
58 changes: 32 additions & 26 deletions node.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package iavl

// NOTE: This file favors int64 as opposed to int for size/counts.
// The Tree on the other hand favors int. This is intentional.

import (
"bytes"
"fmt"
Expand All @@ -17,7 +20,7 @@ type Node struct {
value []byte
version int64
height int8
size int
size int64
hash []byte
leftHash []byte
leftNode *Node
Expand Down Expand Up @@ -51,21 +54,18 @@ func MakeNode(buf []byte) (node *Node, err error) {
n := 1 // Keeps track of bytes read.
buf = buf[n:]

node.size, n, err = wire.GetVarint(buf)
if err != nil {
return nil, err
}
buf = buf[n:]
node.size = wire.GetInt64(buf)
buf = buf[8:]

node.version = wire.GetInt64(buf)
buf = buf[8:]

node.key, n, err = wire.GetByteSlice(buf)
if err != nil {
return nil, err
}
buf = buf[n:]

node.version = wire.GetInt64(buf)
buf = buf[8:]

// Read node body.

if node.isLeaf() {
Expand Down Expand Up @@ -100,14 +100,14 @@ func (node *Node) String() string {
}

// clone creates a shallow copy of a node with its hash set to nil.
func (node *Node) clone() *Node {
func (node *Node) clone(version int64) *Node {
if node.isLeaf() {
cmn.PanicSanity("Attempt to copy a leaf node")
}
return &Node{
key: node.key,
height: node.height,
version: node.version,
version: version,
size: node.size,
hash: nil,
leftHash: node.leftHash,
Expand Down Expand Up @@ -138,7 +138,7 @@ func (node *Node) has(t *Tree, key []byte) (has bool) {
}

// Get a key under the node.
func (node *Node) get(t *Tree, key []byte) (index int, value []byte) {
func (node *Node) get(t *Tree, key []byte) (index int64, value []byte) {
if node.isLeaf() {
switch bytes.Compare(node.key, key) {
case -1:
Expand All @@ -160,7 +160,7 @@ func (node *Node) get(t *Tree, key []byte) (index int, value []byte) {
}
}

func (node *Node) getByIndex(t *Tree, index int) (key []byte, value []byte) {
func (node *Node) getByIndex(t *Tree, index int64) (key []byte, value []byte) {
if node.isLeaf() {
if index == 0 {
return node.key, node.value
Expand Down Expand Up @@ -199,7 +199,7 @@ func (node *Node) _hash() []byte {

// Hash the node and its descendants recursively. This usually mutates all
// descendant nodes. Returns the node hash and number of nodes hashed.
func (node *Node) hashWithCount() ([]byte, int) {
func (node *Node) hashWithCount() ([]byte, int64) {
if node.hash != nil {
return node.hash, 0
}
Expand All @@ -220,14 +220,14 @@ func (node *Node) hashWithCount() ([]byte, int) {
// child hashes to be already set.
func (node *Node) writeHashBytes(w io.Writer) (n int, err error) {
wire.WriteInt8(node.height, w, &n, &err)
wire.WriteVarint(node.size, w, &n, &err)
wire.WriteInt64(node.size, w, &n, &err)
wire.WriteInt64(node.version, w, &n, &err)

// Key is not written for inner nodes, unlike writeBytes.

if node.isLeaf() {
wire.WriteByteSlice(node.key, w, &n, &err)
wire.WriteByteSlice(node.value, w, &n, &err)
wire.WriteInt64(node.version, w, &n, &err)
} else {
if node.leftHash == nil || node.rightHash == nil {
cmn.PanicSanity("Found an empty child hash")
Expand All @@ -240,7 +240,7 @@ func (node *Node) writeHashBytes(w io.Writer) (n int, err error) {

// Writes the node's hash to the given io.Writer.
// This function has the side-effect of calling hashWithCount.
func (node *Node) writeHashBytesRecursively(w io.Writer) (n int, hashCount int, err error) {
func (node *Node) writeHashBytesRecursively(w io.Writer) (n int, hashCount int64, err error) {
if node.leftNode != nil {
leftHash, leftCount := node.leftNode.hashWithCount()
node.leftHash = leftHash
Expand All @@ -259,11 +259,11 @@ func (node *Node) writeHashBytesRecursively(w io.Writer) (n int, hashCount int,
// Writes the node as a serialized byte slice to the supplied io.Writer.
func (node *Node) writeBytes(w io.Writer) (n int, err error) {
wire.WriteInt8(node.height, w, &n, &err)
wire.WriteVarint(node.size, w, &n, &err)
wire.WriteInt64(node.size, w, &n, &err)
wire.WriteInt64(node.version, w, &n, &err)

// Unlike writeHashBytes, key is written for inner nodes.
wire.WriteByteSlice(node.key, w, &n, &err)
wire.WriteInt64(node.version, w, &n, &err)

if node.isLeaf() {
wire.WriteByteSlice(node.value, w, &n, &err)
Expand Down Expand Up @@ -311,7 +311,7 @@ func (node *Node) set(t *Tree, key []byte, value []byte) (
}
} else {
orphaned = append(orphaned, node)
node = node.clone()
node = node.clone(version)

if bytes.Compare(key, node.key) < 0 {
var leftOrphaned []*Node
Expand Down Expand Up @@ -341,6 +341,8 @@ func (node *Node) set(t *Tree, key []byte, value []byte) (
func (node *Node) remove(t *Tree, key []byte) (
newHash []byte, newNode *Node, newKey []byte, value []byte, orphaned []*Node,
) {
version := t.version + 1

if node.isLeaf() {
if bytes.Equal(key, node.key) {
return nil, nil, nil, node.value, []*Node{node}
Expand All @@ -362,7 +364,7 @@ func (node *Node) remove(t *Tree, key []byte) (
}
orphaned = append(orphaned, node)

newNode := node.clone()
newNode := node.clone(version)
newNode.leftHash, newNode.leftNode = newLeftHash, newLeftNode
newNode.calcHeightAndSize(t)
newNode, balanceOrphaned := newNode.balance(t)
Expand All @@ -382,7 +384,7 @@ func (node *Node) remove(t *Tree, key []byte) (
}
orphaned = append(orphaned, node)

newNode := node.clone()
newNode := node.clone(version)
newNode.rightHash, newNode.rightNode = newRightHash, newRightNode
if newKey != nil {
newNode.key = newKey
Expand Down Expand Up @@ -410,10 +412,12 @@ func (node *Node) getRightNode(t *Tree) *Node {

// Rotate right and return the new node and orphan.
func (node *Node) rotateRight(t *Tree) (newNode *Node, orphan *Node) {
version := t.version + 1

// TODO: optimize balance & rotate.
node = node.clone()
node = node.clone(version)
l := node.getLeftNode(t)
_l := l.clone()
_l := l.clone(version)

_lrHash, _lrCached := _l.rightHash, _l.rightNode
_l.rightHash, _l.rightNode = node.hash, node
Expand All @@ -427,10 +431,12 @@ func (node *Node) rotateRight(t *Tree) (newNode *Node, orphan *Node) {

// Rotate left and return the new node and orphan.
func (node *Node) rotateLeft(t *Tree) (newNode *Node, orphan *Node) {
version := t.version + 1

// TODO: optimize balance & rotate.
node = node.clone()
node = node.clone(version)
r := node.getRightNode(t)
_r := r.clone()
_r := r.clone(version)

_rlHash, _rlCached := _r.leftHash, _r.leftNode
_r.leftHash, _r.leftNode = node.hash, node
Expand Down
Loading

0 comments on commit 8ffd5bf

Please sign in to comment.