73 lines
1.2 KiB
Go
73 lines
1.2 KiB
Go
// Copyright (C) 2018 Marius Schellenberger
|
|
|
|
package filter
|
|
|
|
import (
|
|
"math/rand"
|
|
"sync"
|
|
)
|
|
|
|
// DefaultCacheSize is the default cache size
|
|
const DefaultCacheSize = 100
|
|
|
|
// QueryCache can be used to cache queries
|
|
type QueryCache struct {
|
|
// protects m
|
|
sync.RWMutex
|
|
|
|
m map[string]*Query
|
|
size int
|
|
}
|
|
|
|
// NewQueryCache returns a new QueryCache
|
|
func NewQueryCache(size int) *QueryCache {
|
|
if size <= 0 {
|
|
size = DefaultCacheSize
|
|
}
|
|
return &QueryCache{
|
|
m: make(map[string]*Query),
|
|
size: size,
|
|
}
|
|
}
|
|
|
|
// NewQuery looks for the given query in the cache and returns it.
|
|
// If the query is not found it will be generated and inserted in the cache..
|
|
func (qc *QueryCache) NewQuery(s string) (q *Query, err error) {
|
|
q = qc.Lookup(s)
|
|
if q != nil {
|
|
return
|
|
}
|
|
q, err = NewQuery(s)
|
|
if err != nil {
|
|
return
|
|
}
|
|
qc.Lock()
|
|
defer qc.Unlock()
|
|
if len(qc.m) == qc.size {
|
|
qc.clean()
|
|
}
|
|
qc.m[s] = q
|
|
return
|
|
}
|
|
|
|
// Lookup looks for a given query string and returns the query object or nil.
|
|
func (qc *QueryCache) Lookup(s string) *Query {
|
|
qc.RLock()
|
|
defer qc.RUnlock()
|
|
if q, ok := qc.m[s]; ok {
|
|
return q
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (qc *QueryCache) clean() {
|
|
i := rand.Intn(len(qc.m))
|
|
var k string
|
|
for k = range qc.m {
|
|
if i == 0 {
|
|
break
|
|
}
|
|
i--
|
|
}
|
|
delete(qc.m, k)
|
|
}
|