lazifying

This commit is contained in:
Jae Kwon 2014-05-21 21:48:41 -07:00
parent 850144f3e7
commit f66c552ef2
4 changed files with 171 additions and 108 deletions

54
merkle/db.go Normal file
View File

@ -0,0 +1,54 @@
package merkle
import (
"fmt"
"github.com/syndtr/goleveldb/leveldb"
"path"
)
type LDBDatabase struct {
db *leveldb.DB
}
func NewLDBDatabase(name string) (*LDBDatabase, error) {
dbPath := path.Join(name)
db, err := leveldb.OpenFile(dbPath, nil)
if err != nil {
return nil, err
}
database := &LDBDatabase{db: db}
return database, nil
}
func (db *LDBDatabase) Put(key []byte, value []byte) {
err := db.db.Put(key, value, nil)
if err != nil {
fmt.Println("Error put", err)
}
}
func (db *LDBDatabase) Get(key []byte) ([]byte, error) {
return db.db.Get(key, nil)
}
func (db *LDBDatabase) Delete(key []byte) error {
return db.db.Delete(key, nil)
}
func (db *LDBDatabase) Db() *leveldb.DB {
return db.db
}
func (db *LDBDatabase) Close() {
db.db.Close()
}
func (db *LDBDatabase) Print() {
iter := db.db.NewIterator(nil, nil)
for iter.Next() {
key := iter.Key()
value := iter.Value()
fmt.Printf("%x(%d): %v ", key, len(key), value)
}
}

View File

@ -1,9 +1,9 @@
package merkle package merkle
import ( import (
//"fmt" "bytes"
"math" "math"
//"hash" "io"
"crypto/sha256" "crypto/sha256"
) )
@ -18,13 +18,17 @@ func NewIAVLTree() *IAVLTree {
} }
func (self *IAVLTree) Root() Node { func (self *IAVLTree) Root() Node {
return self.root.Copy(true) return self.root
} }
func (self *IAVLTree) Size() int { func (self *IAVLTree) Size() uint64 {
return self.root.Size() return self.root.Size()
} }
func (self *IAVLTree) Height() uint8 {
return self.root.Height()
}
func (self *IAVLTree) Has(key Key) bool { func (self *IAVLTree) Has(key Key) bool {
return self.root.Has(key) return self.root.Has(key)
} }
@ -34,7 +38,7 @@ func (self *IAVLTree) Put(key Key, value Value) (err error) {
return nil return nil
} }
func (self *IAVLTree) Hash() ([]byte, int) { func (self *IAVLTree) Hash() ([]byte, uint64) {
return self.root.Hash() return self.root.Hash()
} }
@ -56,27 +60,29 @@ func (self *IAVLTree) Remove(key Key) (value Value, err error) {
type IAVLNode struct { type IAVLNode struct {
key Key key Key
value Value value Value
height int size uint64
height uint8
hash []byte hash []byte
left *IAVLNode left *IAVLNode
right *IAVLNode right *IAVLNode
// volatile
flags byte
} }
func (self *IAVLNode) Copy(copyHash bool) *IAVLNode { func (self *IAVLNode) Copy() *IAVLNode {
if self == nil { if self == nil {
return nil return nil
} }
var hash []byte
if copyHash {
hash = self.hash
}
return &IAVLNode{ return &IAVLNode{
key: self.key, key: self.key,
value: self.value, value: self.value,
size: self.size,
height: self.height, height: self.height,
hash: hash,
left: self.left, left: self.left,
right: self.right, right: self.right,
hash: nil,
flags: byte(0),
} }
} }
@ -98,11 +104,11 @@ func (self *IAVLNode) Right() Node {
return self.right return self.right
} }
func (self *IAVLNode) Size() int { func (self *IAVLNode) Size() uint64 {
if self == nil { if self == nil {
return 0 return 0
} }
return 1 + self.left.Size() + self.right.Size() return self.size
} }
func (self *IAVLNode) Has(key Key) (has bool) { func (self *IAVLNode) Has(key Key) (has bool) {
@ -131,54 +137,74 @@ func (self *IAVLNode) Get(key Key) (value Value, err error) {
} }
} }
func (self *IAVLNode) Hash() ([]byte, int) { func (self *IAVLNode) Bytes() []byte {
b := new(bytes.Buffer)
self.WriteTo(b)
return b.Bytes()
}
func (self *IAVLNode) Hash() ([]byte, uint64) {
if self == nil { if self == nil {
return nil, 0 return nil, 0
} }
if self.hash != nil { if self.hash != nil {
return self.hash, 0 return self.hash, 0
} }
hasher := sha256.New() hasher := sha256.New()
hashCount := 1 _, hashCount, err := self.WriteTo(hasher)
if err != nil { panic(err) }
self.hash = hasher.Sum(nil)
return self.hash, hashCount
}
func (self *IAVLNode) WriteTo(writer io.Writer) (written int64, hashCount uint64, err error) {
write := func(bytes []byte) {
if err == nil {
var n int
n, err = writer.Write(bytes)
written += int64(n)
}
}
// node descriptor // node descriptor
nodeDesc := byte(0) nodeDesc := byte(0)
if self.value != nil { nodeDesc |= 0x01 } if self.value != nil { nodeDesc |= 0x01 }
if self.left != nil { nodeDesc |= 0x02 } if self.left != nil { nodeDesc |= 0x02 }
if self.right != nil { nodeDesc |= 0x04 } if self.right != nil { nodeDesc |= 0x04 }
hasher.Write([]byte{nodeDesc}) write([]byte{nodeDesc})
// node key // node key
keyBytes := self.key.Bytes() keyBytes := self.key.Bytes()
if len(keyBytes) > 255 { panic("key is too long") } if len(keyBytes) > 255 { panic("key is too long") }
hasher.Write([]byte{byte(len(keyBytes))}) write([]byte{byte(len(keyBytes))})
hasher.Write(keyBytes) write(keyBytes)
// node value // node value
if self.value != nil { if self.value != nil {
valueBytes := self.value.Bytes() valueBytes := self.value.Bytes()
if len(valueBytes) > math.MaxUint32 { panic("value is too long") } if len(valueBytes) > math.MaxUint32 { panic("value is too long") }
hasher.Write([]byte{byte(len(valueBytes))}) write([]byte{byte(len(valueBytes))})
hasher.Write(valueBytes) write(valueBytes)
} }
// left child // left child
if self.left != nil { if self.left != nil {
leftHash, leftCount := self.left.Hash() leftHash, leftCount := self.left.Hash()
hashCount += leftCount hashCount += leftCount
hasher.Write(leftHash) write(leftHash)
} }
// right child // right child
if self.right != nil { if self.right != nil {
rightHash, rightCount := self.right.Hash() rightHash, rightCount := self.right.Hash()
hashCount += rightCount hashCount += rightCount
hasher.Write(rightHash) write(rightHash)
} }
self.hash = hasher.Sum(nil) return written, hashCount+1, err
return self.hash, hashCount
} }
// Returns a new tree (unless node is the root) & a copy of the popped node. // Returns a new tree (unless node is the root) & a copy of the popped node.
@ -202,84 +228,64 @@ func (self *IAVLNode) pop_node(node *IAVLNode) (new_self, new_node *IAVLNode) {
} else { } else {
n = nil n = nil
} }
node = node.Copy(false) node = node.Copy()
node.left = nil node.left = nil
node.right = nil node.right = nil
node.calc_height_and_size()
return n, node return n, node
} else { } else {
self = self.Copy(false) self = self.Copy()
if node.key.Less(self.key) { if node.key.Less(self.key) {
self.left, node = self.left.pop_node(node) self.left, node = self.left.pop_node(node)
} else { } else {
self.right, node = self.right.pop_node(node) self.right, node = self.right.pop_node(node)
} }
self.calc_height() self.calc_height_and_size()
return self, node return self, node
} }
} }
// Pushes the node to the tree, returns a new tree
func (self *IAVLNode) push_node(node *IAVLNode) *IAVLNode {
if node == nil {
panic("node can't be nil")
} else if node.left != nil || node.right != nil {
panic("node must now be a leaf")
}
self = self.Copy(false)
if self == nil {
node.height = 1
return node
} else if node.key.Less(self.key) {
self.left = self.left.push_node(node)
} else {
self.right = self.right.push_node(node)
}
self.calc_height()
return self
}
func (self *IAVLNode) rotate_right() *IAVLNode { func (self *IAVLNode) rotate_right() *IAVLNode {
self = self.Copy(false) self = self.Copy()
sl := self.left.Copy(false) sl := self.left.Copy()
slr := sl.right slr := sl.right
sl.right = self sl.right = self
self.left = slr self.left = slr
self.calc_height() self.calc_height_and_size()
sl.calc_height() sl.calc_height_and_size()
return sl return sl
} }
func (self *IAVLNode) rotate_left() *IAVLNode { func (self *IAVLNode) rotate_left() *IAVLNode {
self = self.Copy(false) self = self.Copy()
sr := self.right.Copy(false) sr := self.right.Copy()
srl := sr.left srl := sr.left
sr.left = self sr.left = self
self.right = srl self.right = srl
self.calc_height() self.calc_height_and_size()
sr.calc_height() sr.calc_height_and_size()
return sr return sr
} }
func (self *IAVLNode) calc_height() { func (self *IAVLNode) calc_height_and_size() {
self.height = max(self.left.Height(), self.right.Height()) + 1 self.height = maxUint8(self.left.Height(), self.right.Height()) + 1
self.size = self.left.Size() + self.right.Size() + 1
} }
func (self *IAVLNode) calc_balance() int { func (self *IAVLNode) calc_balance() int {
if self == nil { if self == nil {
return 0 return 0
} }
return self.left.Height() - self.right.Height() return int(self.left.Height()) - int(self.right.Height())
} }
func (self *IAVLNode) balance() (new_self *IAVLNode) { func (self *IAVLNode) balance() (new_self *IAVLNode) {
@ -290,8 +296,9 @@ func (self *IAVLNode) balance() (new_self *IAVLNode) {
return self.rotate_right() return self.rotate_right()
} else { } else {
// Left Right Case // Left Right Case
self = self.Copy(false) self = self.Copy()
self.left = self.left.rotate_left() self.left = self.left.rotate_left()
//self.calc_height_and_size()
return self.rotate_right() return self.rotate_right()
} }
} }
@ -301,8 +308,9 @@ func (self *IAVLNode) balance() (new_self *IAVLNode) {
return self.rotate_left() return self.rotate_left()
} else { } else {
// Right Left Case // Right Left Case
self = self.Copy(false) self = self.Copy()
self.right = self.right.rotate_right() self.right = self.right.rotate_right()
//self.calc_height_and_size()
return self.rotate_left() return self.rotate_left()
} }
} }
@ -313,10 +321,10 @@ func (self *IAVLNode) balance() (new_self *IAVLNode) {
// TODO: don't clear the hash if the value hasn't changed. // TODO: don't clear the hash if the value hasn't changed.
func (self *IAVLNode) Put(key Key, value Value) (_ *IAVLNode, updated bool) { func (self *IAVLNode) Put(key Key, value Value) (_ *IAVLNode, updated bool) {
if self == nil { if self == nil {
return &IAVLNode{key: key, value: value, height: 1, hash: nil}, false return &IAVLNode{key: key, value: value, height: 1, size: 1, hash: nil}, false
} }
self = self.Copy(false) self = self.Copy()
if self.key.Equals(key) { if self.key.Equals(key) {
self.value = value self.value = value
@ -331,7 +339,7 @@ func (self *IAVLNode) Put(key Key, value Value) (_ *IAVLNode, updated bool) {
if updated { if updated {
return self, updated return self, updated
} else { } else {
self.calc_height() self.calc_height_and_size()
return self.balance(), updated return self.balance(), updated
} }
} }
@ -350,6 +358,7 @@ func (self *IAVLNode) Remove(key Key) (new_self *IAVLNode, value Value, err erro
} }
new_self.left = self.left new_self.left = self.left
new_self.right = self.right new_self.right = self.right
new_self.calc_height_and_size()
return new_self, self.value, nil return new_self, self.value, nil
} else if self.left == nil { } else if self.left == nil {
return self.right, self.value, nil return self.right, self.value, nil
@ -371,7 +380,7 @@ func (self *IAVLNode) Remove(key Key) (new_self *IAVLNode, value Value, err erro
} else if err != nil { // some other error } else if err != nil { // some other error
return self, value, err return self, value, err
} }
self = self.Copy(false) self = self.Copy()
self.left = new_left self.left = new_left
} else { } else {
if self.right == nil { if self.right == nil {
@ -384,14 +393,14 @@ func (self *IAVLNode) Remove(key Key) (new_self *IAVLNode, value Value, err erro
} else if err != nil { // some other error } else if err != nil { // some other error
return self, value, err return self, value, err
} }
self = self.Copy(false) self = self.Copy()
self.right = new_right self.right = new_right
} }
self.calc_height() self.calc_height_and_size()
return self.balance(), value, err return self.balance(), value, err
} }
func (self *IAVLNode) Height() int { func (self *IAVLNode) Height() uint8 {
if self == nil { if self == nil {
return 0 return 0
} }
@ -418,14 +427,7 @@ func (self *IAVLNode) rmd() (*IAVLNode) {
return self._md(func(node *IAVLNode)*IAVLNode { return node.right }) return self._md(func(node *IAVLNode)*IAVLNode { return node.right })
} }
func abs(i int) int { func maxUint8(a, b uint8) uint8 {
if i < 0 {
return -i
}
return i
}
func max(a, b int) int {
if a > b { if a > b {
return a return a
} }

View File

@ -68,7 +68,7 @@ func TestImmutableAvlPutHasGetRemove(t *testing.T) {
if !updated { if !updated {
t.Error("should have been updated") t.Error("should have been updated")
} }
if tree.Size() != (i+1) { if tree.Size() != uint64(i+1) {
t.Error("size was wrong", tree.Size(), i+1) t.Error("size was wrong", tree.Size(), i+1)
} }
} }
@ -106,7 +106,7 @@ func TestImmutableAvlPutHasGetRemove(t *testing.T) {
t.Error("wrong value") t.Error("wrong value")
} }
} }
if tree.Size() != (len(records) - (i+1)) { if tree.Size() != uint64(len(records) - (i+1)) {
t.Error("size was wrong", tree.Size(), (len(records) - (i+1))) t.Error("size was wrong", tree.Size(), (len(records) - (i+1)))
} }
} }
@ -173,8 +173,12 @@ func TestGriffin(t *testing.T) {
// Convenience for a new node // Convenience for a new node
N := func(l *IAVLNode, i int, r *IAVLNode) *IAVLNode { N := func(l *IAVLNode, i int, r *IAVLNode) *IAVLNode {
n := &IAVLNode{Int32(i), nil, -1, nil, l, r} n := &IAVLNode{
n.calc_height() key: Int32(i),
left: l,
right: r,
}
n.calc_height_and_size()
n.Hash() n.Hash()
return n return n
} }
@ -193,7 +197,7 @@ func TestGriffin(t *testing.T) {
} }
} }
expectHash := func(n2 *IAVLNode, hashCount int) { expectHash := func(n2 *IAVLNode, hashCount uint64) {
// ensure number of new hash calculations is as expected. // ensure number of new hash calculations is as expected.
hash, count := n2.Hash() hash, count := n2.Hash()
if count != hashCount { if count != hashCount {
@ -213,7 +217,7 @@ func TestGriffin(t *testing.T) {
} }
} }
expectPut := func(n *IAVLNode, i int, repr string, hashCount int) { expectPut := func(n *IAVLNode, i int, repr string, hashCount uint64) {
n2, updated := n.Put(Int32(i), nil) n2, updated := n.Put(Int32(i), nil)
// ensure node was added & structure is as expected. // ensure node was added & structure is as expected.
if updated == true || P(n2) != repr { if updated == true || P(n2) != repr {
@ -224,7 +228,7 @@ func TestGriffin(t *testing.T) {
expectHash(n2, hashCount) expectHash(n2, hashCount)
} }
expectRemove := func(n *IAVLNode, i int, repr string, hashCount int) { expectRemove := func(n *IAVLNode, i int, repr string, hashCount uint64) {
n2, value, err := n.Remove(Int32(i)) n2, value, err := n.Remove(Int32(i))
// ensure node was added & structure is as expected. // ensure node was added & structure is as expected.
if value != nil || err != nil || P(n2) != repr { if value != nil || err != nil || P(n2) != repr {

View File

@ -5,43 +5,46 @@ import (
) )
type Value interface { type Value interface {
Bytes() []byte Bytes() []byte
} }
type Key interface { type Key interface {
Equals(b Key) bool Equals(b Key) bool
Less(b Key) bool Less(b Key) bool
Bytes() []byte Bytes() []byte
} }
type Tree interface { type Tree interface {
Root() Node Root() Node
Size() int Size() uint64
Has(key Key) bool Height() uint8
Get(key Key) (value Value, err error) Has(key Key) bool
Hash() ([]byte, int) Get(key Key) (Value, error)
Hash() ([]byte, uint64)
Put(key Key, value Value) (err error) Put(Key, Value) (err error)
Remove(key Key) (value Value, err error) Remove(Key) (Value, error)
} }
type Node interface { type Node interface {
Key() Key Key() Key
Value() Value Value() Value
Left() Node Left() Node
Right() Node Right() Node
Size() int Size() uint64
Has(key Key) bool Height() uint8
Get(key Key) (value Value, err error) Has(Key) bool
Hash() ([]byte, int) Get(Key) (Value, error)
Hash() ([]byte, uint64)
Bytes() []byte
Put(key Key, value Value) (_ *IAVLNode, updated bool) Put(Key, Value) (*IAVLNode, bool)
Remove(key Key) (_ *IAVLNode, value Value, err error) Remove(Key) (*IAVLNode, Value, error)
} }
type NodeIterator func() (node Node) type NodeIterator func() Node
func NotFound(key Key) error { func NotFound(key Key) error {
return fmt.Errorf("Key was not found.") return fmt.Errorf("Key was not found.")