Skip to content

Commit

Permalink
Add first version of new hyper batch tree
Browse files Browse the repository at this point in the history
Co-authored-by: Gabriel Díaz <[email protected]>
  • Loading branch information
aalda and gdiazlo committed Feb 25, 2019
1 parent 364c83b commit 425e1c2
Show file tree
Hide file tree
Showing 18 changed files with 1,684 additions and 21 deletions.
46 changes: 40 additions & 6 deletions balloon/cache/test_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,62 @@
package cache

import (
"bytes"
"fmt"

"github.com/bbva/qed/storage"
"github.com/bbva/qed/testutils/rand"
"github.com/bbva/qed/util"
)

type FakeCache struct {
FixedValue []byte
cached map[[keySize]byte][]byte
}

func NewFakeCache(fixedValue []byte) *FakeCache {
return &FakeCache{fixedValue}
return &FakeCache{
FixedValue: fixedValue,
cached: make(map[[keySize]byte][]byte),
}
}

func (c FakeCache) Get([]byte) ([]byte, bool) {
return []byte{0x0}, true
func (c FakeCache) Get(key []byte) ([]byte, bool) {
var k [keySize]byte
copy(k[:], key)
value, ok := c.cached[k]
if !ok {
return []byte{0x0}, true
}
return value, ok
}

func (c *FakeCache) Put(key []byte, value []byte) {}
func (c *FakeCache) Put(key []byte, value []byte) {
var k [keySize]byte
copy(k[:], key)
c.cached[k] = value
}

func (c *FakeCache) Fill(r storage.KVPairReader) error { return nil }
func (c *FakeCache) Fill(r storage.KVPairReader) error {
return fmt.Errorf("Operation not supported")
}

func (c FakeCache) Size() int { return 1 }
func (c FakeCache) Size() int {
return len(c.cached)
}

func (c FakeCache) Equal(o *FakeCache) bool {
for k, v1 := range c.cached {
v2, ok := o.cached[k]
if !ok {
return false
}
if !bytes.Equal(v1, v2) {
return false
}
}
return true
}

type FakeKVPairReader struct {
Remaining uint64
Expand Down
2 changes: 1 addition & 1 deletion balloon/history/pruning/insert_visitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
type InsertVisitor struct {
hasher hashing.Hasher
cache cache.ModifiableCache
storagePrefix byte
storagePrefix byte // TODO shall i remove this?

mutations []*storage.Mutation
}
Expand Down
22 changes: 12 additions & 10 deletions balloon/history/pruning/insert_visitor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,22 @@ func TestInsertVisitor(t *testing.T) {
))),
expectedMutations: []*storage.Mutation{
{
Prefix: storage.HyperCachePrefix,
Prefix: storage.HistoryCachePrefix,
Key: pos(7, 0).Bytes(),
Value: []byte{7},
},
{
Prefix: storage.HyperCachePrefix,
Prefix: storage.HistoryCachePrefix,
Key: pos(6, 1).Bytes(),
Value: []byte{7},
},
{
Prefix: storage.HyperCachePrefix,
Prefix: storage.HistoryCachePrefix,
Key: pos(4, 2).Bytes(),
Value: []byte{7},
},
{
Prefix: storage.HyperCachePrefix,
Prefix: storage.HistoryCachePrefix,
Key: pos(0, 3).Bytes(),
Value: []byte{7},
},
Expand All @@ -60,15 +60,17 @@ func TestInsertVisitor(t *testing.T) {
}

for i, c := range testCases {
visitor := NewInsertVisitor(
hashing.NewFakeXorHasher(),
cache.NewFakeCache([]byte{0x0}),
storage.HyperCachePrefix,
)
cache := cache.NewFakeCache([]byte{0x0})
visitor := NewInsertVisitor(hashing.NewFakeXorHasher(), cache, storage.HistoryCachePrefix)

c.op.Accept(visitor)

mutations := visitor.Result()
assert.ElementsMatchf(t, mutations, c.expectedMutations, "Mutation error in test case %d", i)
assert.ElementsMatchf(t, c.expectedMutations, mutations, "Mutation error in test case %d", i)
for _, e := range c.expectedElements {
v, _ := cache.Get(e.Pos.Bytes())
assert.Equalf(t, e.Digest, v, "The cached element %v should be cached in test case %d", e, i)
}
}
}

Expand Down
6 changes: 3 additions & 3 deletions balloon/history/pruning/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ func (o PutCacheOp) Position() *navigation.Position {
}

func (o PutCacheOp) String() string {
return fmt.Sprintf("PutCacheOp[ %v ]", o.Operation)
return fmt.Sprintf("PutCacheOp( %v )", o.Operation)
}

func NewMutateOp(op Operation) *MutateOp {
Expand All @@ -163,7 +163,7 @@ func (o MutateOp) Position() *navigation.Position {
}

func (o MutateOp) String() string {
return fmt.Sprintf("MutateOp[ %v ]", o.Operation)
return fmt.Sprintf("MutateOp( %v )", o.Operation)
}

func NewCollectOp(op Operation) *CollectOp {
Expand All @@ -181,5 +181,5 @@ func (o CollectOp) Position() *navigation.Position {
}

func (o CollectOp) String() string {
return fmt.Sprintf("CollectOp[ %v ]", o.Operation)
return fmt.Sprintf("CollectOp( %v )", o.Operation)
}
113 changes: 113 additions & 0 deletions balloon/hyper2/navigation/position.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
Copyright 2018 Banco Bilbao Vizcaya Argentaria, S.A.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package navigation

import (
"fmt"

"github.com/bbva/qed/util"
)

const KeySize = 34

type Position struct {
Index []byte
Height uint16

serialized [KeySize]byte
numBits uint16
}

func NewPosition(index []byte, height uint16) *Position {
var b [KeySize]byte // Size of the index plus 2 bytes for the height
copy(b[:], index[:len(index)])
copy(b[len(index):], util.Uint16AsBytes(height))
return &Position{
Index: index,
Height: height,
serialized: b, // memoized
numBits: uint16(len(index)) * 8,
}
}

func NewRootPosition(numBits uint16) *Position {
return NewPosition(make([]byte, numBits/8), numBits)
}

func (p Position) Bytes() []byte {
return p.serialized[:]
}

func (p Position) FixedBytes() [KeySize]byte {
return p.serialized
}

func (p Position) String() string {
return fmt.Sprintf("Pos(%d, %d)", p.Index, p.Height)
}

func (p Position) StringId() string {
return fmt.Sprintf("%x|%d", p.Index, p.Height)
}

func (p Position) Left() *Position {
if p.IsLeaf() {
return nil
}
return NewPosition(p.Index, p.Height-1)
}

func (p Position) Right() *Position {
if p.IsLeaf() {
return nil
}
return NewPosition(p.splitBase(), p.Height-1)
}

func (p Position) IsLeaf() bool {
return p.Height == 0
}

func (p Position) FirstDescendant() *Position {
if p.IsLeaf() {
return &p
}
return NewPosition(p.Index, 0)
}

func (p Position) LastDescendant() *Position {
if p.IsLeaf() {
return &p
}
index := make([]byte, p.numBits/8)
copy(index, p.Index)
for bit := p.numBits - p.Height; bit < p.numBits; bit++ {
bitSet(index, bit)
}
return NewPosition(index, 0)
}

func (p Position) splitBase() []byte {
splitBit := p.numBits - p.Height
split := make([]byte, p.numBits/8)
copy(split, p.Index)
if splitBit < p.numBits {
bitSet(split, splitBit)
}
return split
}

func bitSet(bits []byte, i uint16) {
bits[i/8] |= 1 << uint(7-i%8)
}
Loading

0 comments on commit 425e1c2

Please sign in to comment.