pkg/index/posting/roaring/roaring.go (177 lines of code) (raw):

// Licensed to Apache Software Foundation (ASF) under one or more contributor // license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright // ownership. Apache Software Foundation (ASF) licenses this file to you 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 roaring implements the posting list by a roaring bitmap. package roaring import ( "github.com/RoaringBitmap/roaring/roaring64" "github.com/pkg/errors" "github.com/apache/skywalking-banyandb/pkg/index/posting" ) var ( // DummyPostingList is an empty list. DummyPostingList = NewPostingList() errIntersectRoaringOnly = errors.New("Intersect only supported between roaringDocId sets") errUnionRoaringOnly = errors.New("Union only supported between roaringDocId sets") errDifferenceRoaringOnly = errors.New("Difference only supported between roaringDocId sets") ) var _ posting.List = (*postingsList)(nil) // postingsList abstracts a Roaring Bitmap. type postingsList struct { bitmap *roaring64.Bitmap } func (p *postingsList) Marshall() ([]byte, error) { return p.bitmap.MarshalBinary() } func (p *postingsList) Unmarshall(data []byte) error { return p.bitmap.UnmarshalBinary(data) } // NewPostingList returns a empty posting list. func NewPostingList() posting.List { return &postingsList{ bitmap: roaring64.New(), } } // NewPostingListWithInitialData return a posting list with initialized data. func NewPostingListWithInitialData(data ...uint64) posting.List { list := NewPostingList() for _, d := range data { list.Insert(d) } return list } // NewRange return a posting list added the integers in [start, end). func NewRange(start, end uint64) posting.List { list := &postingsList{ bitmap: roaring64.New(), } list.bitmap.AddRange(start, end) return list } func (p *postingsList) Contains(id uint64) bool { return p.bitmap.Contains(id) } func (p *postingsList) IsEmpty() bool { return p.bitmap.IsEmpty() } func (p *postingsList) Min() (uint64, error) { if p.IsEmpty() { return 0, posting.ErrListEmpty } return p.bitmap.Minimum(), nil } func (p *postingsList) Max() (uint64, error) { if p.IsEmpty() { return 0, posting.ErrListEmpty } return p.bitmap.Maximum(), nil } func (p *postingsList) Len() int { return int(p.bitmap.GetCardinality()) } func (p *postingsList) Iterator() posting.Iterator { return &roaringIterator{ iter: p.bitmap.Iterator(), } } func (p *postingsList) Clone() posting.List { return &postingsList{ bitmap: p.bitmap.Clone(), } } func (p *postingsList) Equal(other posting.List) bool { if p.Len() != other.Len() { return false } iter := p.Iterator() otherIter := other.Iterator() for iter.Next() { if !otherIter.Next() { return false } if iter.Current() != otherIter.Current() { return false } } return true } func (p *postingsList) Insert(id uint64) { p.bitmap.Add(id) } func (p *postingsList) Intersect(other posting.List) error { o, ok := other.(*postingsList) if !ok { return errIntersectRoaringOnly } p.bitmap.And(o.bitmap) return nil } func (p *postingsList) Difference(other posting.List) error { o, ok := other.(*postingsList) if !ok { return errDifferenceRoaringOnly } p.bitmap.AndNot(o.bitmap) return nil } func (p *postingsList) Union(other posting.List) error { o, ok := other.(*postingsList) if !ok { return errUnionRoaringOnly } p.bitmap.Or(o.bitmap) return nil } func (p *postingsList) UnionMany(others []posting.List) error { for _, other := range others { err := p.Union(other) if err != nil { return err } } return nil } func (p *postingsList) AddIterator(iter posting.Iterator) error { for iter.Next() { p.Insert(iter.Current()) } return nil } func (p *postingsList) AddRange(minVal, maxVal uint64) error { for i := minVal; i < maxVal; i++ { p.bitmap.Add(i) } return nil } func (p *postingsList) RemoveRange(minVal, maxVal uint64) error { for i := minVal; i < maxVal; i++ { p.bitmap.Remove(i) } return nil } func (p *postingsList) Reset() { p.bitmap.Clear() } func (p *postingsList) SizeInBytes() int64 { return int64(p.bitmap.GetSizeInBytes()) } type roaringIterator struct { iter roaring64.IntIterable64 current uint64 closed bool } func (it *roaringIterator) Current() uint64 { return it.current } func (it *roaringIterator) Next() bool { if it.closed || !it.iter.HasNext() { return false } v := it.iter.Next() it.current = v return true } func (it *roaringIterator) Close() error { it.closed = true return nil } func (p *postingsList) ToSlice() []uint64 { iter := p.Iterator() defer iter.Close() s := make([]uint64, 0, p.Len()) for iter.Next() { s = append(s, iter.Current()) } return s }