mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 10:54:59 +00:00
commit
3c9ca6c2c4
6 changed files with 72 additions and 7 deletions
34
cache.go
34
cache.go
|
|
@ -54,7 +54,7 @@ type Cache interface {
|
|||
SetStats(s StatsClient)
|
||||
}
|
||||
|
||||
// LRUCache represents a least recently used Cache implemenation.
|
||||
// LRUCache represents a least recently used Cache implementation.
|
||||
type LRUCache struct {
|
||||
cache *lru.Cache
|
||||
counts map[uint64]uint64
|
||||
|
|
@ -483,3 +483,35 @@ func (s *SimpleCache) Fetch(id uint64) (*Bitmap, bool) {
|
|||
func (s *SimpleCache) Add(id uint64, b *Bitmap) {
|
||||
s.cache[id] = b
|
||||
}
|
||||
|
||||
// NopCache represents a no-op Cache implementation.
|
||||
type NopCache struct {
|
||||
stats StatsClient
|
||||
}
|
||||
|
||||
// Ensure NopCache implements Cache.
|
||||
var _ Cache = &NopCache{}
|
||||
|
||||
// NewNopCache returns a new instance of NopCache.
|
||||
func NewNopCache() *NopCache {
|
||||
return &NopCache{
|
||||
stats: NopStatsClient,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *NopCache) Add(id uint64, n uint64) {}
|
||||
func (c *NopCache) BulkAdd(id uint64, n uint64) {}
|
||||
func (c *NopCache) Get(id uint64) uint64 { return 0 }
|
||||
func (c *NopCache) IDs() []uint64 { return make([]uint64, 0, 0) }
|
||||
|
||||
func (c *NopCache) Invalidate() {}
|
||||
func (c *NopCache) Len() int { return 0 }
|
||||
func (c *NopCache) Recalculate() {
|
||||
}
|
||||
func (c *NopCache) SetStats(s StatsClient) {
|
||||
c.stats = s
|
||||
}
|
||||
|
||||
func (c *NopCache) Top() []BitmapPair {
|
||||
return []BitmapPair{}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -249,6 +249,8 @@ func (f *Fragment) openCache() error {
|
|||
f.cache = NewRankCache(f.CacheSize)
|
||||
case CacheTypeLRU:
|
||||
f.cache = NewLRUCache(f.CacheSize)
|
||||
case CacheTypeNone:
|
||||
f.cache = NewNopCache()
|
||||
default:
|
||||
return ErrInvalidCacheType
|
||||
}
|
||||
|
|
@ -702,6 +704,10 @@ func (f *Fragment) Top(opt TopOptions) ([]Pair, error) {
|
|||
}
|
||||
|
||||
func (f *Fragment) topBitmapPairs(rowIDs []uint64) []BitmapPair {
|
||||
// Don't retrieve from storage if CacheTypeNone.
|
||||
if f.CacheType == CacheTypeNone {
|
||||
return f.cache.Top()
|
||||
}
|
||||
// If no specific rows are requested, retrieve top rows.
|
||||
if len(rowIDs) == 0 {
|
||||
f.mu.Lock()
|
||||
|
|
|
|||
|
|
@ -415,6 +415,24 @@ func TestFragment_TopN_IDs(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// Ensure a fragment return none if CacheTypeNone is set
|
||||
func TestFragment_TopN_NopCache(t *testing.T) {
|
||||
f := test.MustOpenFragment("i", "f", pilosa.ViewStandard, 0, pilosa.CacheTypeNone)
|
||||
defer f.Close()
|
||||
|
||||
// Set bits on various rows.
|
||||
f.MustSetBits(100, 1, 2, 3)
|
||||
f.MustSetBits(101, 4, 5, 6, 7)
|
||||
f.MustSetBits(102, 8, 9, 10, 11, 12)
|
||||
|
||||
// Retrieve top rows.
|
||||
if pairs, err := f.Top(pilosa.TopOptions{RowIDs: []uint64{100, 101, 200}}); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !reflect.DeepEqual(pairs, []pilosa.Pair{}) {
|
||||
t.Fatalf("unexpected pairs: %s", spew.Sdump(pairs))
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the fragment cache limit works
|
||||
func TestFragment_TopN_CacheSize(t *testing.T) {
|
||||
slice := uint64(0)
|
||||
|
|
|
|||
3
frame.go
3
frame.go
|
|
@ -905,12 +905,13 @@ func (p importBitSet) Less(i, j int) bool { return p.rowIDs[i] < p.rowIDs[j] }
|
|||
const (
|
||||
CacheTypeLRU = "lru"
|
||||
CacheTypeRanked = "ranked"
|
||||
CacheTypeNone = "none"
|
||||
)
|
||||
|
||||
// IsValidCacheType returns true if v is a valid cache type.
|
||||
func IsValidCacheType(v string) bool {
|
||||
switch v {
|
||||
case CacheTypeLRU, CacheTypeRanked:
|
||||
case CacheTypeLRU, CacheTypeRanked, CacheTypeNone:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
|
|
|
|||
6
index.go
6
index.go
|
|
@ -388,16 +388,12 @@ func (i *Index) createFrame(name string, opt FrameOptions) (*Frame, error) {
|
|||
}
|
||||
|
||||
// Validate mutually exclusive options if ranges are enabled.
|
||||
//
|
||||
// NOTE(https://github.com/pilosa/pilosa/issues/399):
|
||||
// Cache type should be validated as "none" once it is allowed.
|
||||
if opt.RangeEnabled {
|
||||
if opt.InverseEnabled {
|
||||
return nil, ErrInverseRangeNotAllowed
|
||||
} else if opt.CacheType != "" && opt.CacheType != CacheTypeLRU {
|
||||
} else if opt.CacheType != "" && opt.CacheType != CacheTypeNone {
|
||||
return nil, ErrRangeCacheNotAllowed
|
||||
}
|
||||
opt.CacheSize = 0
|
||||
} else {
|
||||
if len(opt.Fields) > 0 {
|
||||
return nil, ErrFrameFieldsNotAllowed
|
||||
|
|
|
|||
|
|
@ -149,6 +149,18 @@ func TestIndex_CreateFrame(t *testing.T) {
|
|||
}
|
||||
})
|
||||
|
||||
t.Run("RangeEnabledWithCacheTypeNone", func(t *testing.T) {
|
||||
index := test.MustOpenIndex()
|
||||
defer index.Close()
|
||||
if _, err := index.CreateFrame("f", pilosa.FrameOptions{
|
||||
RangeEnabled: true,
|
||||
CacheType: pilosa.CacheTypeNone,
|
||||
CacheSize: uint32(5),
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ErrFrameFieldsNotAllowed", func(t *testing.T) {
|
||||
index := test.MustOpenIndex()
|
||||
defer index.Close()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue