// Copyright (C) 2017 Marius Schellenberger package filter import ( "math/rand" "sync" ) // QueryCache can be used to cache queries type QueryCache struct { // protects m sync.RWMutex m map[string]Query max int } // NewQueryCache returns a new QueryCache func NewQueryCache(max int) *QueryCache { return &QueryCache{ m: make(map[string]Query), max: max, } } // 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.max { 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) }