diff --git a/internal/bsi/bsi.go b/internal/bsi/bsi.go index d224c705..0e13efff 100644 --- a/internal/bsi/bsi.go +++ b/internal/bsi/bsi.go @@ -33,7 +33,7 @@ func NewBitmap() *Bitmap { // It depends upon the bitmap libraries. It is not thread safe, so // upstream concurrency guards must be provided. type BSI struct { - source Source + Source Source } // NewBSI constructs a new BSI. Note that it is your responsibility to ensure that @@ -48,7 +48,7 @@ func NewBSI(maxValue int64, minValue int64) *BSI { for i := range bitsz + 1 { src.GetOrCreate(i) } - return &BSI{source: src} + return &BSI{Source: src} } // NewDefaultBSI constructs an auto-sized BSI @@ -57,7 +57,7 @@ func NewDefaultBSI() *BSI { } func (b *BSI) Reset() { - if s, ok := b.source.(Reset); ok { + if s, ok := b.Source.(Reset); ok { s.Reset() } } @@ -424,17 +424,17 @@ func (b *BSI) String() string { } func (b *BSI) muex() *roaring.Bitmap { - return b.source.GetOrCreate(0) + return b.Source.GetOrCreate(0) } func (b *BSI) ex() *roaring.Bitmap { - return b.source.Get(0) + return b.Source.Get(0) } func (b *BSI) must(i int) *roaring.Bitmap { - return b.source.GetOrCreate(i + 1) + return b.Source.GetOrCreate(i + 1) } func (b *BSI) get(i int) *roaring.Bitmap { - return b.source.Get(i + 1) + return b.Source.Get(i + 1) } diff --git a/internal/bsi/kv.go b/internal/bsi/kv.go deleted file mode 100644 index b6bf499b..00000000 --- a/internal/bsi/kv.go +++ /dev/null @@ -1,61 +0,0 @@ -package bsi - -import ( - "errors" - "log/slog" - "sync" - - "github.com/dgraph-io/badger/v4" - "github.com/vinceanalytics/vince/internal/encoding" - "github.com/vinceanalytics/vince/internal/models" - "github.com/vinceanalytics/vince/internal/roaring" -) - -type KV struct { - key []byte - mu sync.RWMutex - tx *badger.Txn - cached map[int]*roaring.Bitmap -} - -func NewKV(tx *badger.Txn, ts, shard uint64, field models.Field) *BSI { - key := encoding.Bitmap(ts, shard, field, 0, - make([]byte, encoding.BitmapKeySize)) - kv := &KV{ - key: key, - tx: tx, - cached: make(map[int]*roaring.Bitmap), - } - return &BSI{source: kv} -} - -var _ Source = (*KV)(nil) - -func (kv *KV) GetOrCreate(i int) *roaring.Bitmap { return nil } - -func (kv *KV) Get(i int) *roaring.Bitmap { - kv.mu.RLock() - b, ok := kv.cached[i] - kv.mu.RUnlock() - if ok { - return b - } - kv.mu.Lock() - defer kv.mu.Unlock() - kv.key[len(kv.key)-1] = byte(i) - it, err := kv.tx.Get(kv.key) - if err != nil { - if !errors.Is(err, badger.ErrKeyNotFound) { - slog.Error("reading bitmap", "err", err) - } - return nil - } - value, err := it.ValueCopy(nil) - if err != nil { - slog.Error("copying bitmap", "err", err) - return nil - } - b = roaring.FromBuffer(value) - kv.cached[i] = b - return b -} diff --git a/internal/ro2/source.go b/internal/ro2/source.go new file mode 100644 index 00000000..d93c8678 --- /dev/null +++ b/internal/ro2/source.go @@ -0,0 +1,35 @@ +package ro2 + +import ( + "github.com/vinceanalytics/vince/internal/bsi" + "github.com/vinceanalytics/vince/internal/encoding" + "github.com/vinceanalytics/vince/internal/models" + "github.com/vinceanalytics/vince/internal/roaring" +) + +type KV []*roaring.Bitmap + +func NewKV(tx *Tx, ts, shard uint64, field models.Field) *bsi.BSI { + key := encoding.Bitmap(ts, shard, field, 0, + make([]byte, encoding.BitmapKeySize)) + kv := make(KV, 0, 64) + prefix := key[:len(key)-1] + it := tx.Iter() + for it.Seek(key); it.ValidForPrefix(prefix); it.Next() { + value, _ := it.Item().ValueCopy(nil) + b := roaring.FromBuffer(value) + kv = append(kv, b) + } + return &bsi.BSI{Source: kv} +} + +var _ bsi.Source = (*KV)(nil) + +func (kv KV) GetOrCreate(i int) *roaring.Bitmap { return nil } + +func (kv KV) Get(i int) *roaring.Bitmap { + if i < len(kv) { + return kv[i] + } + return nil +} diff --git a/internal/ro2/tx.go b/internal/ro2/tx.go index 7303c74a..14713372 100644 --- a/internal/ro2/tx.go +++ b/internal/ro2/tx.go @@ -129,7 +129,7 @@ func (tx *Tx) Bitmap(shard, view uint64, field models.Field) *bsi.BSI { if b, ok := tx.bsi[key]; ok { return b } - b := bsi.NewKV(tx.tx, view, shard, field) + b := NewKV(tx, view, shard, field) tx.bsi[key] = b return b }