// 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) }