From 15f8441068a57855497d8a29f0e010bd343387d7 Mon Sep 17 00:00:00 2001 From: Jae Kwon Date: Tue, 3 Jun 2014 17:03:29 -0700 Subject: [PATCH] WriteToBuffer -> WriteTo --- merkle/iavl.go | 56 ++++++++++++++++++-------------- merkle/iavl_test.go | 6 ++-- merkle/int.go | 78 ++++++++++++++++++++------------------------- merkle/string.go | 23 +++++++------ merkle/types.go | 3 +- 5 files changed, 85 insertions(+), 81 deletions(-) diff --git a/merkle/iavl.go b/merkle/iavl.go index aa4d1b8d..008383b5 100644 --- a/merkle/iavl.go +++ b/merkle/iavl.go @@ -1,6 +1,9 @@ package merkle import ( + //"fmt" + "bytes" + "io" "crypto/sha256" ) @@ -191,11 +194,9 @@ func (self *IAVLNode) Hash() (ByteSlice, uint64) { return self.hash, 0 } - size := self.ByteSize() - buf := make([]byte, size, size) hasher := sha256.New() - _, hashCount := self.saveToCountHashes(buf) - hasher.Write(buf) + _, hashCount, err := self.saveToCountHashes(hasher) + if err != nil { panic(err) } self.hash = hasher.Sum(nil) return self.hash, hashCount+1 @@ -217,9 +218,11 @@ func (self *IAVLNode) Save(db Db) { } // save self - buf := make([]byte, self.ByteSize(), self.ByteSize()) - self.WriteTo(buf) - db.Put([]byte(self.hash), buf) + buf := make([]byte, 0, self.ByteSize()) + n, err := self.WriteTo(bytes.NewBuffer(buf)) + if err != nil { panic(err) } + if n != int64(cap(buf)) { panic("unexpected write length") } + db.Put([]byte(self.hash), buf[0:cap(buf)]) self.flags |= IAVLNODE_FLAG_PERSISTED } @@ -321,43 +324,48 @@ func (self *IAVLNode) ByteSize() int { return size } -func (self *IAVLNode) WriteTo(buf []byte) int { - written, _ := self.saveToCountHashes(buf) - return written +func (self *IAVLNode) WriteTo(w io.Writer) (n int64, err error) { + n, _, err = self.saveToCountHashes(w) + return } -func (self *IAVLNode) saveToCountHashes(buf []byte) (int, uint64) { - cur := 0 - hashCount := uint64(0) +func (self *IAVLNode) saveToCountHashes(w io.Writer) (n int64, hashCount uint64, err error) { + var _n int64 // height & size - cur += UInt8(self.height).WriteTo(buf[cur:]) - cur += UInt64(self.size).WriteTo(buf[cur:]) + _n, err = UInt8(self.height).WriteTo(w) + if err != nil { return } else { n += _n } + _n, err = UInt64(self.size).WriteTo(w) + if err != nil { return } else { n += _n } // key - buf[cur] = GetBinaryType(self.key) - cur += 1 - cur += self.key.WriteTo(buf[cur:]) + _n, err = Byte(GetBinaryType(self.key)).WriteTo(w) + if err != nil { return } else { n += _n } + _n, err = self.key.WriteTo(w) + if err != nil { return } else { n += _n } if self.height == 0 { // value - buf[cur] = GetBinaryType(self.value) - cur += 1 + _n, err = Byte(GetBinaryType(self.value)).WriteTo(w) + if err != nil { return } else { n += _n } if self.value != nil { - cur += self.value.WriteTo(buf[cur:]) + _n, err = self.value.WriteTo(w) + if err != nil { return } else { n += _n } } } else { // left leftHash, leftCount := self.left.Hash() hashCount += leftCount - cur += leftHash.WriteTo(buf[cur:]) + _n, err = leftHash.WriteTo(w) + if err != nil { return } else { n += _n } // right rightHash, rightCount := self.right.Hash() hashCount += rightCount - cur += rightHash.WriteTo(buf[cur:]) + _n, err = rightHash.WriteTo(w) + if err != nil { return } else { n += _n } } - return cur, hashCount + return } // Given a placeholder node which has only the hash set, diff --git a/merkle/iavl_test.go b/merkle/iavl_test.go index b009e55e..9a6c11be 100644 --- a/merkle/iavl_test.go +++ b/merkle/iavl_test.go @@ -1,8 +1,7 @@ package merkle -import "testing" - import ( + "testing" "fmt" "os" "bytes" @@ -10,6 +9,7 @@ import ( "encoding/binary" "github.com/tendermint/tendermint/db" "crypto/sha256" + "runtime" ) func init() { @@ -271,6 +271,8 @@ func BenchmarkImmutableAvlTree(b *testing.B) { fmt.Println("ok, starting") + runtime.GC() + b.StartTimer() for i := 0; i < b.N; i++ { r := randomRecord() diff --git a/merkle/int.go b/merkle/int.go index 5d1b6a80..cf12326e 100644 --- a/merkle/int.go +++ b/merkle/int.go @@ -1,6 +1,7 @@ package merkle import ( + "io" "encoding/binary" ) @@ -35,10 +36,9 @@ func (self Byte) ByteSize() int { return 1 } -func (self Byte) WriteTo(b []byte) int { - if cap(b) < 1 { panic("buf too small") } - b[0] = byte(self) - return 1 +func (self Byte) WriteTo(w io.Writer) (int64, error) { + n, err := w.Write([]byte{byte(self)}) + return int64(n), err } func ReadByte(bytes []byte) Byte { @@ -64,10 +64,9 @@ func (self Int8) ByteSize() int { return 1 } -func (self Int8) WriteTo(b []byte) int { - if cap(b) < 1 { panic("buf too small") } - b[0] = byte(self) - return 1 +func (self Int8) WriteTo(w io.Writer) (int64, error) { + n, err := w.Write([]byte{byte(self)}) + return int64(n), err } func ReadInt8(bytes []byte) Int8 { @@ -93,10 +92,9 @@ func (self UInt8) ByteSize() int { return 1 } -func (self UInt8) WriteTo(b []byte) int { - if cap(b) < 1 { panic("buf too small") } - b[0] = byte(self) - return 1 +func (self UInt8) WriteTo(w io.Writer) (int64, error) { + n, err := w.Write([]byte{byte(self)}) + return int64(n), err } func ReadUInt8(bytes []byte) UInt8 { @@ -122,10 +120,9 @@ func (self Int16) ByteSize() int { return 2 } -func (self Int16) WriteTo(b []byte) int { - if cap(b) < 2 { panic("buf too small") } - binary.LittleEndian.PutUint16(b, uint16(self)) - return 2 +func (self Int16) WriteTo(w io.Writer) (int64, error) { + err := binary.Write(w, binary.LittleEndian, int16(self)) + return 2, err } func ReadInt16(bytes []byte) Int16 { @@ -151,10 +148,9 @@ func (self UInt16) ByteSize() int { return 2 } -func (self UInt16) WriteTo(b []byte) int { - if cap(b) < 2 { panic("buf too small") } - binary.LittleEndian.PutUint16(b, uint16(self)) - return 2 +func (self UInt16) WriteTo(w io.Writer) (int64, error) { + err := binary.Write(w, binary.LittleEndian, uint16(self)) + return 2, err } func ReadUInt16(bytes []byte) UInt16 { @@ -180,10 +176,9 @@ func (self Int32) ByteSize() int { return 4 } -func (self Int32) WriteTo(b []byte) int { - if cap(b) < 4 { panic("buf too small") } - binary.LittleEndian.PutUint32(b, uint32(self)) - return 4 +func (self Int32) WriteTo(w io.Writer) (int64, error) { + err := binary.Write(w, binary.LittleEndian, int32(self)) + return 4, err } func ReadInt32(bytes []byte) Int32 { @@ -209,10 +204,9 @@ func (self UInt32) ByteSize() int { return 4 } -func (self UInt32) WriteTo(b []byte) int { - if cap(b) < 4 { panic("buf too small") } - binary.LittleEndian.PutUint32(b, uint32(self)) - return 4 +func (self UInt32) WriteTo(w io.Writer) (int64, error) { + err := binary.Write(w, binary.LittleEndian, uint32(self)) + return 4, err } func ReadUInt32(bytes []byte) UInt32 { @@ -238,10 +232,9 @@ func (self Int64) ByteSize() int { return 8 } -func (self Int64) WriteTo(b []byte) int { - if cap(b) < 8 { panic("buf too small") } - binary.LittleEndian.PutUint64(b, uint64(self)) - return 8 +func (self Int64) WriteTo(w io.Writer) (int64, error) { + err := binary.Write(w, binary.LittleEndian, int64(self)) + return 8, err } func ReadInt64(bytes []byte) Int64 { @@ -267,10 +260,9 @@ func (self UInt64) ByteSize() int { return 8 } -func (self UInt64) WriteTo(b []byte) int { - if cap(b) < 8 { panic("buf too small") } - binary.LittleEndian.PutUint64(b, uint64(self)) - return 8 +func (self UInt64) WriteTo(w io.Writer) (int64, error) { + err := binary.Write(w, binary.LittleEndian, uint64(self)) + return 8, err } func ReadUInt64(bytes []byte) UInt64 { @@ -296,10 +288,9 @@ func (self Int) ByteSize() int { return 8 } -func (self Int) WriteTo(b []byte) int { - if cap(b) < 8 { panic("buf too small") } - binary.LittleEndian.PutUint64(b, uint64(self)) - return 8 +func (self Int) WriteTo(w io.Writer) (int64, error) { + err := binary.Write(w, binary.LittleEndian, int64(self)) + return 8, err } func ReadInt(bytes []byte) Int { @@ -324,10 +315,9 @@ func (self UInt) ByteSize() int { return 8 } -func (self UInt) WriteTo(b []byte) int { - if cap(b) < 8 { panic("buf too small") } - binary.LittleEndian.PutUint64(b, uint64(self)) - return 8 +func (self UInt) WriteTo(w io.Writer) (int64, error) { + err := binary.Write(w, binary.LittleEndian, uint64(self)) + return 8, err } func ReadUInt(bytes []byte) UInt { diff --git a/merkle/string.go b/merkle/string.go index eba14a3c..a7dc3509 100644 --- a/merkle/string.go +++ b/merkle/string.go @@ -1,5 +1,6 @@ package merkle +import "io" import "bytes" type String string @@ -23,11 +24,12 @@ func (self String) ByteSize() int { return len(self)+4 } -func (self String) WriteTo(buf []byte) int { - if len(buf) < self.ByteSize() { panic("buf too small") } - UInt32(len(self)).WriteTo(buf) - copy(buf[4:], []byte(self)) - return len(self)+4 +func (self String) WriteTo(w io.Writer) (n int64, err error) { + var n_ int + _, err = UInt32(len(self)).WriteTo(w) + if err != nil { return n, err } + n_, err = w.Write([]byte(self)) + return int64(n_+4), err } // NOTE: keeps a reference to the original byte slice @@ -59,11 +61,12 @@ func (self ByteSlice) ByteSize() int { return len(self)+4 } -func (self ByteSlice) WriteTo(buf []byte) int { - if len(buf) < self.ByteSize() { panic("buf too small") } - UInt32(len(self)).WriteTo(buf) - copy(buf[4:], self) - return len(self)+4 +func (self ByteSlice) WriteTo(w io.Writer) (n int64, err error) { + var n_ int + _, err = UInt32(len(self)).WriteTo(w) + if err != nil { return n, err } + n_, err = w.Write([]byte(self)) + return int64(n_+4), err } // NOTE: keeps a reference to the original byte slice diff --git a/merkle/types.go b/merkle/types.go index 7d80377f..3e2fbaa9 100644 --- a/merkle/types.go +++ b/merkle/types.go @@ -1,12 +1,13 @@ package merkle import ( + "io" "fmt" ) type Binary interface { ByteSize() int - WriteTo([]byte) int + WriteTo(io.Writer) (int64, error) Equals(Binary) bool }