mirror of
https://github.com/fluencelabs/tendermint
synced 2025-06-25 10:41:41 +00:00
change logger to log15
This commit is contained in:
171
binary/bit_array.go
Normal file
171
binary/bit_array.go
Normal file
@ -0,0 +1,171 @@
|
||||
package binary
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strings"
|
||||
|
||||
. "github.com/tendermint/tendermint/common"
|
||||
)
|
||||
|
||||
// Not goroutine safe
|
||||
type BitArray struct {
|
||||
Bits uint // NOTE: persisted via reflect, must be exported
|
||||
Elems []uint64 // NOTE: persisted via reflect, must be exported
|
||||
}
|
||||
|
||||
func NewBitArray(bits uint) BitArray {
|
||||
return BitArray{bits, make([]uint64, (bits+63)/64)}
|
||||
}
|
||||
|
||||
func (bA BitArray) Size() uint {
|
||||
return bA.Bits
|
||||
}
|
||||
|
||||
func (bA BitArray) IsZero() bool {
|
||||
return bA.Bits == 0
|
||||
}
|
||||
|
||||
// NOTE: behavior is undefined if i >= bA.Bits
|
||||
func (bA BitArray) GetIndex(i uint) bool {
|
||||
if i >= bA.Bits {
|
||||
return false
|
||||
}
|
||||
return bA.Elems[i/64]&uint64(1<<(i%64)) > 0
|
||||
}
|
||||
|
||||
// NOTE: behavior is undefined if i >= bA.Bits
|
||||
func (bA BitArray) SetIndex(i uint, v bool) bool {
|
||||
if i >= bA.Bits {
|
||||
return false
|
||||
}
|
||||
if v {
|
||||
bA.Elems[i/64] |= uint64(1 << (i % 64))
|
||||
} else {
|
||||
bA.Elems[i/64] &= ^uint64(1 << (i % 64))
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (bA BitArray) Copy() BitArray {
|
||||
c := make([]uint64, len(bA.Elems))
|
||||
copy(c, bA.Elems)
|
||||
return BitArray{bA.Bits, c}
|
||||
}
|
||||
|
||||
func (bA BitArray) copyBits(bits uint) BitArray {
|
||||
c := make([]uint64, (bits+63)/64)
|
||||
copy(c, bA.Elems)
|
||||
return BitArray{bits, c}
|
||||
}
|
||||
|
||||
// Returns a BitArray of larger bits size.
|
||||
func (bA BitArray) Or(o BitArray) BitArray {
|
||||
c := bA.copyBits(MaxUint(bA.Bits, o.Bits))
|
||||
for i := 0; i < len(c.Elems); i++ {
|
||||
c.Elems[i] |= o.Elems[i]
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// Returns a BitArray of smaller bit size.
|
||||
func (bA BitArray) And(o BitArray) BitArray {
|
||||
c := bA.copyBits(MinUint(bA.Bits, o.Bits))
|
||||
for i := 0; i < len(c.Elems); i++ {
|
||||
c.Elems[i] &= o.Elems[i]
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (bA BitArray) Not() BitArray {
|
||||
c := bA.Copy()
|
||||
for i := 0; i < len(c.Elems); i++ {
|
||||
c.Elems[i] = ^c.Elems[i]
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (bA BitArray) Sub(o BitArray) BitArray {
|
||||
if bA.Bits > o.Bits {
|
||||
c := bA.Copy()
|
||||
for i := 0; i < len(o.Elems)-1; i++ {
|
||||
c.Elems[i] &= ^c.Elems[i]
|
||||
}
|
||||
i := uint(len(o.Elems) - 1)
|
||||
if i >= 0 {
|
||||
for idx := i * 64; idx < o.Bits; idx++ {
|
||||
c.SetIndex(idx, c.GetIndex(idx) && !o.GetIndex(idx))
|
||||
}
|
||||
}
|
||||
return c
|
||||
} else {
|
||||
return bA.And(o.Not())
|
||||
}
|
||||
}
|
||||
|
||||
func (bA BitArray) PickRandom() (uint, bool) {
|
||||
length := len(bA.Elems)
|
||||
if length == 0 {
|
||||
return 0, false
|
||||
}
|
||||
randElemStart := rand.Intn(length)
|
||||
for i := 0; i < length; i++ {
|
||||
elemIdx := ((i + randElemStart) % length)
|
||||
if elemIdx < length-1 {
|
||||
if bA.Elems[elemIdx] > 0 {
|
||||
randBitStart := rand.Intn(64)
|
||||
for j := 0; j < 64; j++ {
|
||||
bitIdx := ((j + randBitStart) % 64)
|
||||
if (bA.Elems[elemIdx] & (1 << uint(bitIdx))) > 0 {
|
||||
return 64*uint(elemIdx) + uint(bitIdx), true
|
||||
}
|
||||
}
|
||||
panic("should not happen")
|
||||
}
|
||||
} else {
|
||||
// Special case for last elem, to ignore straggler bits
|
||||
elemBits := int(bA.Bits) % 64
|
||||
if elemBits == 0 {
|
||||
elemBits = 64
|
||||
}
|
||||
randBitStart := rand.Intn(elemBits)
|
||||
for j := 0; j < elemBits; j++ {
|
||||
bitIdx := ((j + randBitStart) % elemBits)
|
||||
if (bA.Elems[elemIdx] & (1 << uint(bitIdx))) > 0 {
|
||||
return 64*uint(elemIdx) + uint(bitIdx), true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func (bA BitArray) String() string {
|
||||
return bA.StringIndented("")
|
||||
}
|
||||
|
||||
func (bA BitArray) StringIndented(indent string) string {
|
||||
lines := []string{}
|
||||
bits := ""
|
||||
for i := uint(0); i < bA.Bits; i++ {
|
||||
if bA.GetIndex(i) {
|
||||
bits += "X"
|
||||
} else {
|
||||
bits += "_"
|
||||
}
|
||||
if i%100 == 99 {
|
||||
lines = append(lines, bits)
|
||||
bits = ""
|
||||
}
|
||||
if i%10 == 9 {
|
||||
bits += " "
|
||||
}
|
||||
if i%50 == 49 {
|
||||
bits += " "
|
||||
}
|
||||
}
|
||||
if len(bits) > 0 {
|
||||
lines = append(lines, bits)
|
||||
}
|
||||
return fmt.Sprintf("BA{%v:%v}", bA.Bits, strings.Join(lines, indent))
|
||||
}
|
161
binary/bit_array_test.go
Normal file
161
binary/bit_array_test.go
Normal file
@ -0,0 +1,161 @@
|
||||
package binary
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
. "github.com/tendermint/tendermint/common"
|
||||
)
|
||||
|
||||
func randBitArray(bits uint) (BitArray, []byte) {
|
||||
src := RandBytes(int((bits + 7) / 8))
|
||||
bA := NewBitArray(bits)
|
||||
for i := uint(0); i < uint(len(src)); i++ {
|
||||
for j := uint(0); j < 8; j++ {
|
||||
if i*8+j >= bits {
|
||||
return bA, src
|
||||
}
|
||||
setBit := src[i]&(1<<j) > 0
|
||||
bA.SetIndex(i*8+j, setBit)
|
||||
}
|
||||
}
|
||||
return bA, src
|
||||
}
|
||||
|
||||
func TestReadWriteEmptyBitarray(t *testing.T) {
|
||||
bA1 := BitArray{}
|
||||
buf, n, err := new(bytes.Buffer), new(int64), new(error)
|
||||
WriteBinary(bA1, buf, n, err)
|
||||
if *err != nil {
|
||||
t.Error("Failed to write empty bitarray")
|
||||
}
|
||||
|
||||
bA2 := ReadBinary(BitArray{}, buf, n, err).(BitArray)
|
||||
if *err != nil {
|
||||
t.Error("Failed to read empty bitarray")
|
||||
}
|
||||
if bA2.Bits != 0 {
|
||||
t.Error("Expected to get bA2.Bits 0")
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadWriteBitarray(t *testing.T) {
|
||||
|
||||
// Make random bA1
|
||||
bA1, testData := randBitArray(64*10 + 8) // not divisible by 64
|
||||
|
||||
// Write it
|
||||
buf, n, err := new(bytes.Buffer), new(int64), new(error)
|
||||
WriteBinary(bA1, buf, n, err)
|
||||
if *err != nil {
|
||||
t.Error("Failed to write bitarray")
|
||||
}
|
||||
|
||||
fmt.Printf("Bytes: %X", buf.Bytes())
|
||||
|
||||
// Read it
|
||||
bA2 := ReadBinary(BitArray{}, buf, n, err).(BitArray)
|
||||
if *err != nil {
|
||||
t.Error("Failed to read bitarray")
|
||||
}
|
||||
testData2 := make([]byte, len(testData))
|
||||
for i := uint(0); i < uint(len(testData)); i++ {
|
||||
for j := uint(0); j < 8; j++ {
|
||||
if bA2.GetIndex(i*8 + j) {
|
||||
testData2[i] |= 1 << j
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compare testData
|
||||
if !bytes.Equal(testData, testData2) {
|
||||
t.Errorf("Not the same:\n%X\n%X", testData, testData2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAnd(t *testing.T) {
|
||||
|
||||
bA1, _ := randBitArray(51)
|
||||
bA2, _ := randBitArray(31)
|
||||
bA3 := bA1.And(bA2)
|
||||
|
||||
if bA3.Bits != 31 {
|
||||
t.Error("Expected min bits", bA3.Bits)
|
||||
}
|
||||
if len(bA3.Elems) != len(bA2.Elems) {
|
||||
t.Error("Expected min elems length")
|
||||
}
|
||||
for i := uint(0); i < bA3.Bits; i++ {
|
||||
expected := bA1.GetIndex(i) && bA2.GetIndex(i)
|
||||
if bA3.GetIndex(i) != expected {
|
||||
t.Error("Wrong bit from bA3", i, bA1.GetIndex(i), bA2.GetIndex(i), bA3.GetIndex(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestOr(t *testing.T) {
|
||||
|
||||
bA1, _ := randBitArray(51)
|
||||
bA2, _ := randBitArray(31)
|
||||
bA3 := bA1.Or(bA2)
|
||||
|
||||
if bA3.Bits != 51 {
|
||||
t.Error("Expected max bits")
|
||||
}
|
||||
if len(bA3.Elems) != len(bA1.Elems) {
|
||||
t.Error("Expected max elems length")
|
||||
}
|
||||
for i := uint(0); i < bA3.Bits; i++ {
|
||||
expected := bA1.GetIndex(i) || bA2.GetIndex(i)
|
||||
if bA3.GetIndex(i) != expected {
|
||||
t.Error("Wrong bit from bA3", i, bA1.GetIndex(i), bA2.GetIndex(i), bA3.GetIndex(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSub1(t *testing.T) {
|
||||
|
||||
bA1, _ := randBitArray(31)
|
||||
bA2, _ := randBitArray(51)
|
||||
bA3 := bA1.Sub(bA2)
|
||||
|
||||
if bA3.Bits != bA1.Bits {
|
||||
t.Error("Expected bA1 bits")
|
||||
}
|
||||
if len(bA3.Elems) != len(bA1.Elems) {
|
||||
t.Error("Expected bA1 elems length")
|
||||
}
|
||||
for i := uint(0); i < bA3.Bits; i++ {
|
||||
expected := bA1.GetIndex(i)
|
||||
if bA2.GetIndex(i) {
|
||||
expected = false
|
||||
}
|
||||
if bA3.GetIndex(i) != expected {
|
||||
t.Error("Wrong bit from bA3", i, bA1.GetIndex(i), bA2.GetIndex(i), bA3.GetIndex(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSub2(t *testing.T) {
|
||||
|
||||
bA1, _ := randBitArray(51)
|
||||
bA2, _ := randBitArray(31)
|
||||
bA3 := bA1.Sub(bA2)
|
||||
|
||||
if bA3.Bits != bA1.Bits {
|
||||
t.Error("Expected bA1 bits")
|
||||
}
|
||||
if len(bA3.Elems) != len(bA1.Elems) {
|
||||
t.Error("Expected bA1 elems length")
|
||||
}
|
||||
for i := uint(0); i < bA3.Bits; i++ {
|
||||
expected := bA1.GetIndex(i)
|
||||
if i < bA2.Bits && bA2.GetIndex(i) {
|
||||
expected = false
|
||||
}
|
||||
if bA3.GetIndex(i) != expected {
|
||||
t.Error("Wrong bit from bA3")
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,7 @@
|
||||
package binary
|
||||
|
||||
import (
|
||||
"github.com/op/go-logging"
|
||||
"gopkg.in/inconshreveable/log15.v2"
|
||||
)
|
||||
|
||||
var log = logging.MustGetLogger("binary")
|
||||
|
||||
func SetBinaryLogger(l *logging.Logger) {
|
||||
log = l
|
||||
}
|
||||
var log = log15.New("module", "binary")
|
@ -6,6 +6,8 @@ import (
|
||||
"io"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
. "github.com/tendermint/tendermint/common"
|
||||
)
|
||||
|
||||
type TypeInfo struct {
|
||||
@ -113,7 +115,7 @@ func readReflect(rv reflect.Value, rt reflect.Type, r Unreader, n *int64, err *e
|
||||
// Read TypeByte prefix
|
||||
if typeInfo.HasTypeByte {
|
||||
typeByte := ReadByte(r, n, err)
|
||||
log.Debug("Read TypeByte: %X", typeByte)
|
||||
log.Debug("Read typebyte", "typeByte", typeByte)
|
||||
if typeByte != typeInfo.TypeByte {
|
||||
*err = errors.New(fmt.Sprintf("Expected TypeByte of %X but got %X", typeInfo.TypeByte, typeByte))
|
||||
return
|
||||
@ -126,12 +128,12 @@ func readReflect(rv reflect.Value, rt reflect.Type, r Unreader, n *int64, err *e
|
||||
if elemRt.Kind() == reflect.Uint8 {
|
||||
// Special case: Byteslices
|
||||
byteslice := ReadByteSlice(r, n, err)
|
||||
log.Debug("Read byteslice: %X", byteslice)
|
||||
log.Debug("Read byteslice", "bytes", byteslice)
|
||||
rv.Set(reflect.ValueOf(byteslice))
|
||||
} else {
|
||||
// Read length
|
||||
length := int(ReadUvarint(r, n, err))
|
||||
log.Debug("Read length: %v", length)
|
||||
log.Debug(Fmt("Read length: %v", length))
|
||||
sliceRv := reflect.MakeSlice(rt, length, length)
|
||||
// Read elems
|
||||
for i := 0; i < length; i++ {
|
||||
@ -154,57 +156,57 @@ func readReflect(rv reflect.Value, rt reflect.Type, r Unreader, n *int64, err *e
|
||||
|
||||
case reflect.String:
|
||||
str := ReadString(r, n, err)
|
||||
log.Debug("Read string: %v", str)
|
||||
log.Debug(Fmt("Read string: %v", str))
|
||||
rv.SetString(str)
|
||||
|
||||
case reflect.Int64:
|
||||
num := ReadUint64(r, n, err)
|
||||
log.Debug("Read num: %v", num)
|
||||
log.Debug(Fmt("Read num: %v", num))
|
||||
rv.SetInt(int64(num))
|
||||
|
||||
case reflect.Int32:
|
||||
num := ReadUint32(r, n, err)
|
||||
log.Debug("Read num: %v", num)
|
||||
log.Debug(Fmt("Read num: %v", num))
|
||||
rv.SetInt(int64(num))
|
||||
|
||||
case reflect.Int16:
|
||||
num := ReadUint16(r, n, err)
|
||||
log.Debug("Read num: %v", num)
|
||||
log.Debug(Fmt("Read num: %v", num))
|
||||
rv.SetInt(int64(num))
|
||||
|
||||
case reflect.Int8:
|
||||
num := ReadUint8(r, n, err)
|
||||
log.Debug("Read num: %v", num)
|
||||
log.Debug(Fmt("Read num: %v", num))
|
||||
rv.SetInt(int64(num))
|
||||
|
||||
case reflect.Int:
|
||||
num := ReadUvarint(r, n, err)
|
||||
log.Debug("Read num: %v", num)
|
||||
log.Debug(Fmt("Read num: %v", num))
|
||||
rv.SetInt(int64(num))
|
||||
|
||||
case reflect.Uint64:
|
||||
num := ReadUint64(r, n, err)
|
||||
log.Debug("Read num: %v", num)
|
||||
log.Debug(Fmt("Read num: %v", num))
|
||||
rv.SetUint(uint64(num))
|
||||
|
||||
case reflect.Uint32:
|
||||
num := ReadUint32(r, n, err)
|
||||
log.Debug("Read num: %v", num)
|
||||
log.Debug(Fmt("Read num: %v", num))
|
||||
rv.SetUint(uint64(num))
|
||||
|
||||
case reflect.Uint16:
|
||||
num := ReadUint16(r, n, err)
|
||||
log.Debug("Read num: %v", num)
|
||||
log.Debug(Fmt("Read num: %v", num))
|
||||
rv.SetUint(uint64(num))
|
||||
|
||||
case reflect.Uint8:
|
||||
num := ReadUint8(r, n, err)
|
||||
log.Debug("Read num: %v", num)
|
||||
log.Debug(Fmt("Read num: %v", num))
|
||||
rv.SetUint(uint64(num))
|
||||
|
||||
case reflect.Uint:
|
||||
num := ReadUvarint(r, n, err)
|
||||
log.Debug("Read num: %v", num)
|
||||
log.Debug(Fmt("Read num: %v", num))
|
||||
rv.SetUint(uint64(num))
|
||||
|
||||
default:
|
||||
|
Reference in New Issue
Block a user