mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-10-06 10:57:51 +00:00
b+tree for Containers interface
This commit is contained in:
parent
fab493c42b
commit
ce052c133c
4 changed files with 138 additions and 13 deletions
125
roaring/containers_btree.go
Normal file
125
roaring/containers_btree.go
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
package roaring
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
btree "github.com/pilosa/b"
|
||||
)
|
||||
|
||||
func cmp(a, b uint64) int {
|
||||
return int(a - b)
|
||||
}
|
||||
|
||||
func NewBTreeContainers() *BTreeContainers {
|
||||
return &BTreeContainers{
|
||||
tree: btree.TreeNew(cmp),
|
||||
}
|
||||
}
|
||||
|
||||
type BTreeContainers struct {
|
||||
tree *btree.Tree
|
||||
|
||||
lastKey uint64
|
||||
lastContainer *container
|
||||
}
|
||||
|
||||
func (btc *BTreeContainers) Get(key uint64) *container {
|
||||
var c *container
|
||||
el, ok := btc.tree.Get(key)
|
||||
if ok {
|
||||
c = el.(*container)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (btc *BTreeContainers) Put(key uint64, c *container) {
|
||||
btc.tree.Set(key, c)
|
||||
}
|
||||
|
||||
func (btc *BTreeContainers) Remove(key uint64) {
|
||||
btc.tree.Delete(key)
|
||||
}
|
||||
|
||||
func (btc *BTreeContainers) GetOrCreate(key uint64) *container {
|
||||
// Check the last* cache for same container.
|
||||
if key == btc.lastKey && btc.lastContainer != nil {
|
||||
return btc.lastContainer
|
||||
}
|
||||
|
||||
btc.lastKey = key
|
||||
v, ok := btc.tree.Get(key)
|
||||
if !ok {
|
||||
cont := newContainer()
|
||||
btc.tree.Set(key, cont)
|
||||
btc.lastContainer = cont
|
||||
return cont
|
||||
}
|
||||
|
||||
btc.lastContainer = v.(*container)
|
||||
return btc.lastContainer
|
||||
}
|
||||
|
||||
func (btc *BTreeContainers) Clone() Containers {
|
||||
nbtc := NewBTreeContainers()
|
||||
|
||||
itr, err := btc.tree.SeekFirst()
|
||||
if err == io.EOF {
|
||||
return nbtc
|
||||
}
|
||||
for {
|
||||
k, v, err := itr.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
nbtc.tree.Set(k, v.(*container).clone())
|
||||
}
|
||||
|
||||
return nbtc
|
||||
}
|
||||
|
||||
func (btc *BTreeContainers) Last() (key uint64, c *container) {
|
||||
if btc.tree.Len() == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
k, v := btc.tree.Last()
|
||||
return k, v.(*container)
|
||||
}
|
||||
|
||||
func (btc *BTreeContainers) Size() int {
|
||||
return btc.tree.Len()
|
||||
}
|
||||
|
||||
func (btc *BTreeContainers) Iterator(key uint64) (citer Contiterator, found bool) {
|
||||
e, ok := btc.tree.Seek(key)
|
||||
if ok {
|
||||
found = true
|
||||
}
|
||||
|
||||
return &BTCIterator{
|
||||
e: e,
|
||||
}, found
|
||||
}
|
||||
|
||||
type BTCIterator struct {
|
||||
e *btree.Enumerator
|
||||
key interface{}
|
||||
val interface{}
|
||||
}
|
||||
|
||||
func (i *BTCIterator) Next() bool {
|
||||
|
||||
k, v, err := i.e.Next()
|
||||
if err == io.EOF {
|
||||
return false
|
||||
}
|
||||
i.key = k
|
||||
i.val = v
|
||||
return true
|
||||
}
|
||||
|
||||
func (i *BTCIterator) Value() (uint64, *container) {
|
||||
if i.val == nil {
|
||||
return 0, nil
|
||||
}
|
||||
return i.key.(uint64), i.val.(*container)
|
||||
}
|
||||
|
|
@ -5,19 +5,19 @@ import (
|
|||
)
|
||||
|
||||
func TestContainersIterator(t *testing.T) {
|
||||
slc := NewSkipListContainers()
|
||||
itr, found := slc.Iterator(0)
|
||||
btc := NewBTreeContainers()
|
||||
itr, found := btc.Iterator(0)
|
||||
if found {
|
||||
t.Fatalf("shouldn't have found 0 in empty slc")
|
||||
t.Fatalf("shouldn't have found 0 in empty btc")
|
||||
}
|
||||
if itr.Next() {
|
||||
t.Fatal("Next() should be false for empty slc")
|
||||
t.Fatal("Next() should be false for empty btc")
|
||||
}
|
||||
|
||||
slc.Put(1, &container{n: 1})
|
||||
slc.Put(2, &container{n: 2})
|
||||
btc.Put(1, &container{n: 1})
|
||||
btc.Put(2, &container{n: 2})
|
||||
|
||||
itr, found = slc.Iterator(0)
|
||||
itr, found = btc.Iterator(0)
|
||||
if found {
|
||||
t.Fatalf("shouldn't have found 0")
|
||||
}
|
||||
|
|
@ -39,11 +39,11 @@ func TestContainersIterator(t *testing.T) {
|
|||
t.Fatalf("itr should be done, but got true")
|
||||
}
|
||||
|
||||
slc.Put(3, &container{n: 3})
|
||||
slc.Put(5, &container{n: 5})
|
||||
slc.Put(6, &container{n: 6})
|
||||
btc.Put(3, &container{n: 3})
|
||||
btc.Put(5, &container{n: 5})
|
||||
btc.Put(6, &container{n: 6})
|
||||
|
||||
itr, found = slc.Iterator(3)
|
||||
itr, found = btc.Iterator(3)
|
||||
if !itr.Next() {
|
||||
t.Fatalf("3 should be next, but got false")
|
||||
}
|
||||
|
|
@ -60,7 +60,7 @@ func TestContainersIterator(t *testing.T) {
|
|||
t.Fatalf("Wrong k/v, exp: 5,5 got: %v,%v", key, val.n)
|
||||
}
|
||||
|
||||
itr, found = slc.Iterator(4)
|
||||
itr, found = btc.Iterator(4)
|
||||
if found {
|
||||
t.Fatalf("shouldn't have found 4")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ type Bitmap struct {
|
|||
// NewBitmap returns a Bitmap with an initial set of values.
|
||||
func NewBitmap(a ...uint64) *Bitmap {
|
||||
b := &Bitmap{
|
||||
conts: NewSkipListContainers(),
|
||||
conts: NewBTreeContainers(),
|
||||
}
|
||||
b.Add(a...)
|
||||
return b
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue