Browse Source

lazifying

pull/9/head
Jae Kwon 11 years ago
parent
commit
f66c552ef2
4 changed files with 173 additions and 110 deletions
  1. +54
    -0
      merkle/db.go
  2. +81
    -79
      merkle/iavl.go
  3. +11
    -7
      merkle/iavl_test.go
  4. +27
    -24
      merkle/types.go

+ 54
- 0
merkle/db.go 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)
}
}

+ 81
- 79
merkle/iavl.go View File

@ -1,9 +1,9 @@
package merkle
import (
//"fmt"
"bytes"
"math"
//"hash"
"io"
"crypto/sha256"
)
@ -18,13 +18,17 @@ func NewIAVLTree() *IAVLTree {
}
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()
}
func (self *IAVLTree) Height() uint8 {
return self.root.Height()
}
func (self *IAVLTree) Has(key Key) bool {
return self.root.Has(key)
}
@ -34,7 +38,7 @@ func (self *IAVLTree) Put(key Key, value Value) (err error) {
return nil
}
func (self *IAVLTree) Hash() ([]byte, int) {
func (self *IAVLTree) Hash() ([]byte, uint64) {
return self.root.Hash()
}
@ -56,27 +60,29 @@ func (self *IAVLTree) Remove(key Key) (value Value, err error) {
type IAVLNode struct {
key Key
value Value
height int
size uint64
height uint8
hash []byte
left *IAVLNode
right *IAVLNode
// volatile
flags byte
}
func (self *IAVLNode) Copy(copyHash bool) *IAVLNode {
func (self *IAVLNode) Copy() *IAVLNode {
if self == nil {
return nil
}
var hash []byte
if copyHash {
hash = self.hash
}
return &IAVLNode{
key: self.key,
value: self.value,
size: self.size,
height: self.height,
hash: hash,
left: self.left,
right: self.right,
hash: nil,
flags: byte(0),
}
}
@ -98,11 +104,11 @@ func (self *IAVLNode) Right() Node {
return self.right
}
func (self *IAVLNode) Size() int {
func (self *IAVLNode) Size() uint64 {
if self == nil {
return 0
}
return 1 + self.left.Size() + self.right.Size()
return self.size
}
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 {
return nil, 0
}
if self.hash != nil {
return self.hash, 0
}
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
nodeDesc := byte(0)
if self.value != nil { nodeDesc |= 0x01 }
if self.left != nil { nodeDesc |= 0x02 }
if self.right != nil { nodeDesc |= 0x04 }
hasher.Write([]byte{nodeDesc})
write([]byte{nodeDesc})
// node key
keyBytes := self.key.Bytes()
if len(keyBytes) > 255 { panic("key is too long") }
hasher.Write([]byte{byte(len(keyBytes))})
hasher.Write(keyBytes)
write([]byte{byte(len(keyBytes))})
write(keyBytes)
// node value
if self.value != nil {
valueBytes := self.value.Bytes()
if len(valueBytes) > math.MaxUint32 { panic("value is too long") }
hasher.Write([]byte{byte(len(valueBytes))})
hasher.Write(valueBytes)
write([]byte{byte(len(valueBytes))})
write(valueBytes)
}
// left child
if self.left != nil {
leftHash, leftCount := self.left.Hash()
hashCount += leftCount
hasher.Write(leftHash)
write(leftHash)
}
// right child
if self.right != nil {
rightHash, rightCount := self.right.Hash()
hashCount += rightCount
hasher.Write(rightHash)
write(rightHash)
}
self.hash = hasher.Sum(nil)
return self.hash, hashCount
return written, hashCount+1, err
}
// 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 {
n = nil
}
node = node.Copy(false)
node = node.Copy()
node.left = nil
node.right = nil
node.calc_height_and_size()
return n, node
} else {
self = self.Copy(false)
self = self.Copy()
if node.key.Less(self.key) {
self.left, node = self.left.pop_node(node)
} else {
self.right, node = self.right.pop_node(node)
}
self.calc_height()
self.calc_height_and_size()
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 {
self = self.Copy(false)
sl := self.left.Copy(false)
self = self.Copy()
sl := self.left.Copy()
slr := sl.right
sl.right = self
self.left = slr
self.calc_height()
sl.calc_height()
self.calc_height_and_size()
sl.calc_height_and_size()
return sl
}
func (self *IAVLNode) rotate_left() *IAVLNode {
self = self.Copy(false)
sr := self.right.Copy(false)
self = self.Copy()
sr := self.right.Copy()
srl := sr.left
sr.left = self
self.right = srl
self.calc_height()
sr.calc_height()
self.calc_height_and_size()
sr.calc_height_and_size()
return sr
}
func (self *IAVLNode) calc_height() {
self.height = max(self.left.Height(), self.right.Height()) + 1
func (self *IAVLNode) calc_height_and_size() {
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 {
if self == nil {
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) {
@ -290,8 +296,9 @@ func (self *IAVLNode) balance() (new_self *IAVLNode) {
return self.rotate_right()
} else {
// Left Right Case
self = self.Copy(false)
self = self.Copy()
self.left = self.left.rotate_left()
//self.calc_height_and_size()
return self.rotate_right()
}
}
@ -301,8 +308,9 @@ func (self *IAVLNode) balance() (new_self *IAVLNode) {
return self.rotate_left()
} else {
// Right Left Case
self = self.Copy(false)
self = self.Copy()
self.right = self.right.rotate_right()
//self.calc_height_and_size()
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.
func (self *IAVLNode) Put(key Key, value Value) (_ *IAVLNode, updated bool) {
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) {
self.value = value
@ -331,7 +339,7 @@ func (self *IAVLNode) Put(key Key, value Value) (_ *IAVLNode, updated bool) {
if updated {
return self, updated
} else {
self.calc_height()
self.calc_height_and_size()
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.right = self.right
new_self.calc_height_and_size()
return new_self, self.value, nil
} else if self.left == 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
return self, value, err
}
self = self.Copy(false)
self = self.Copy()
self.left = new_left
} else {
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
return self, value, err
}
self = self.Copy(false)
self = self.Copy()
self.right = new_right
}
self.calc_height()
self.calc_height_and_size()
return self.balance(), value, err
}
func (self *IAVLNode) Height() int {
func (self *IAVLNode) Height() uint8 {
if self == nil {
return 0
}
@ -418,14 +427,7 @@ func (self *IAVLNode) rmd() (*IAVLNode) {
return self._md(func(node *IAVLNode)*IAVLNode { return node.right })
}
func abs(i int) int {
if i < 0 {
return -i
}
return i
}
func max(a, b int) int {
func maxUint8(a, b uint8) uint8 {
if a > b {
return a
}


+ 11
- 7
merkle/iavl_test.go View File

@ -68,7 +68,7 @@ func TestImmutableAvlPutHasGetRemove(t *testing.T) {
if !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)
}
}
@ -106,7 +106,7 @@ func TestImmutableAvlPutHasGetRemove(t *testing.T) {
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)))
}
}
@ -173,8 +173,12 @@ func TestGriffin(t *testing.T) {
// Convenience for a new node
N := func(l *IAVLNode, i int, r *IAVLNode) *IAVLNode {
n := &IAVLNode{Int32(i), nil, -1, nil, l, r}
n.calc_height()
n := &IAVLNode{
key: Int32(i),
left: l,
right: r,
}
n.calc_height_and_size()
n.Hash()
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.
hash, count := n2.Hash()
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)
// ensure node was added & structure is as expected.
if updated == true || P(n2) != repr {
@ -224,7 +228,7 @@ func TestGriffin(t *testing.T) {
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))
// ensure node was added & structure is as expected.
if value != nil || err != nil || P(n2) != repr {


+ 27
- 24
merkle/types.go View File

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


Loading…
Cancel
Save