mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-07 05:46:32 +00:00
TypedTree.
This commit is contained in:
@@ -4,7 +4,9 @@ import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
. "github.com/tendermint/tendermint/binary"
|
||||
. "github.com/tendermint/tendermint/common"
|
||||
"github.com/tendermint/tendermint/db"
|
||||
|
||||
@@ -232,6 +234,49 @@ func TestPersistence(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTypedTree(t *testing.T) {
|
||||
db := db.NewMemDB()
|
||||
|
||||
// Construct some tree and save it
|
||||
t1 := NewTypedTree(NewIAVLTree(db), BasicCodec, BasicCodec)
|
||||
t1.Set(uint8(1), "uint8(1)")
|
||||
t1.Set(uint16(1), "uint16(1)")
|
||||
t1.Set(uint32(1), "uint32(1)")
|
||||
t1.Set(uint64(1), "uint64(1)")
|
||||
t1.Set("byteslice01", []byte{byte(0x00), byte(0x01)})
|
||||
t1.Set("byteslice23", []byte{byte(0x02), byte(0x03)})
|
||||
t1.Set("time", time.Unix(123, 0))
|
||||
t1.Set("nil", nil)
|
||||
t1Hash := t1.Tree.Save()
|
||||
|
||||
// Reconstruct tree
|
||||
t2 := NewTypedTree(LoadIAVLTreeFromHash(db, t1Hash), BasicCodec, BasicCodec)
|
||||
if t2.Get(uint8(1)).(string) != "uint8(1)" {
|
||||
t.Errorf("Expected string uint8(1)")
|
||||
}
|
||||
if t2.Get(uint16(1)).(string) != "uint16(1)" {
|
||||
t.Errorf("Expected string uint16(1)")
|
||||
}
|
||||
if t2.Get(uint32(1)).(string) != "uint32(1)" {
|
||||
t.Errorf("Expected string uint32(1)")
|
||||
}
|
||||
if t2.Get(uint64(1)).(string) != "uint64(1)" {
|
||||
t.Errorf("Expected string uint64(1)")
|
||||
}
|
||||
if !bytes.Equal(t2.Get("byteslice01").([]byte), []byte{byte(0x00), byte(0x01)}) {
|
||||
t.Errorf("Expected byteslice 0x00 0x01")
|
||||
}
|
||||
if !bytes.Equal(t2.Get("byteslice23").([]byte), []byte{byte(0x02), byte(0x03)}) {
|
||||
t.Errorf("Expected byteslice 0x02 0x03")
|
||||
}
|
||||
if t2.Get("time").(time.Time).Unix() != 123 {
|
||||
t.Errorf("Expected time 123")
|
||||
}
|
||||
if t2.Get("nil") != nil {
|
||||
t.Errorf("Expected nil")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkHash(b *testing.B) {
|
||||
b.StopTimer()
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@ package merkle
|
||||
import (
|
||||
"bytes"
|
||||
"container/list"
|
||||
. "github.com/tendermint/tendermint/binary"
|
||||
. "github.com/tendermint/tendermint/common"
|
||||
)
|
||||
|
||||
const defaultCacheCapacity = 1000 // TODO make configurable.
|
||||
|
||||
// XXX Make Codec tree.
|
||||
|
||||
/*
|
||||
Immutable AVL Tree (wraps the Node root)
|
||||
|
||||
@@ -81,11 +81,11 @@ func (t *IAVLTree) HashWithCount() ([]byte, uint64) {
|
||||
return t.root.HashWithCount()
|
||||
}
|
||||
|
||||
func (t *IAVLTree) Save() {
|
||||
func (t *IAVLTree) Save() []byte {
|
||||
if t.root == nil {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
t.root.Save(t.ndb)
|
||||
return t.root.Save(t.ndb)
|
||||
}
|
||||
|
||||
func (t *IAVLTree) Get(key []byte) (value []byte) {
|
||||
@@ -117,6 +117,74 @@ func (t *IAVLTree) Copy() Tree {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
type TypedTree struct {
|
||||
Tree Tree
|
||||
keyCodec Codec
|
||||
valueCodec Codec
|
||||
}
|
||||
|
||||
func NewTypedTree(tree Tree, keyCodec, valueCodec Codec) *TypedTree {
|
||||
return &TypedTree{
|
||||
Tree: tree,
|
||||
keyCodec: keyCodec,
|
||||
valueCodec: valueCodec,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TypedTree) Has(key interface{}) bool {
|
||||
bytes, err := t.keyCodec.Write(key)
|
||||
if err != nil {
|
||||
Panicf("Error from keyCodec: %v", err)
|
||||
}
|
||||
return t.Tree.Has(bytes)
|
||||
}
|
||||
|
||||
func (t *TypedTree) Get(key interface{}) interface{} {
|
||||
keyBytes, err := t.keyCodec.Write(key)
|
||||
if err != nil {
|
||||
Panicf("Error from keyCodec: %v", err)
|
||||
}
|
||||
valueBytes := t.Tree.Get(keyBytes)
|
||||
if valueBytes == nil {
|
||||
return nil
|
||||
}
|
||||
value, err := t.valueCodec.Read(valueBytes)
|
||||
if err != nil {
|
||||
Panicf("Error from valueCodec: %v", err)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func (t *TypedTree) Set(key interface{}, value interface{}) bool {
|
||||
keyBytes, err := t.keyCodec.Write(key)
|
||||
if err != nil {
|
||||
Panicf("Error from keyCodec: %v", err)
|
||||
}
|
||||
valueBytes, err := t.valueCodec.Write(value)
|
||||
if err != nil {
|
||||
Panicf("Error from valueCodec: %v", err)
|
||||
}
|
||||
return t.Tree.Set(keyBytes, valueBytes)
|
||||
}
|
||||
|
||||
func (t *TypedTree) Remove(key interface{}) (interface{}, error) {
|
||||
keyBytes, err := t.keyCodec.Write(key)
|
||||
if err != nil {
|
||||
Panicf("Error from keyCodec: %v", err)
|
||||
}
|
||||
valueBytes, err := t.Tree.Remove(keyBytes)
|
||||
if valueBytes == nil {
|
||||
return nil, err
|
||||
}
|
||||
value, err_ := t.valueCodec.Read(valueBytes)
|
||||
if err_ != nil {
|
||||
Panicf("Error from valueCodec: %v", err)
|
||||
}
|
||||
return value, err
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
type nodeElement struct {
|
||||
node *IAVLNode
|
||||
elem *list.Element
|
||||
|
||||
@@ -14,11 +14,11 @@ type Tree interface {
|
||||
Height() uint8
|
||||
Has(key []byte) bool
|
||||
Get(key []byte) []byte
|
||||
Set(key []byte, value []byte) bool
|
||||
Remove(key []byte) ([]byte, error)
|
||||
HashWithCount() ([]byte, uint64)
|
||||
Hash() []byte
|
||||
Save()
|
||||
Set(key []byte, vlaue []byte) bool
|
||||
Remove(key []byte) ([]byte, error)
|
||||
Save() []byte
|
||||
Copy() Tree
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user