mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-15 13:19:53 +05:00
faster cache counter and unified caches
This commit is contained in:
@@ -31,11 +31,17 @@ type timestampedValue struct {
|
||||
value interface{}
|
||||
}
|
||||
|
||||
const (
|
||||
PREFIX_LEN = 4
|
||||
)
|
||||
|
||||
var (
|
||||
xcache = make(map[string]expiringCacheEntry)
|
||||
xMux sync.RWMutex
|
||||
cache = make(map[string]timestampedValue)
|
||||
mux sync.RWMutex
|
||||
xcache = make(map[string]expiringCacheEntry)
|
||||
xMux sync.RWMutex
|
||||
cache = make(map[string]timestampedValue)
|
||||
mux sync.RWMutex
|
||||
cMux sync.Mutex
|
||||
counters = make(map[string]int64)
|
||||
)
|
||||
|
||||
// The main function to cache with expiration
|
||||
@@ -46,6 +52,7 @@ func (xe *XEntry) XCache(key string, expire time.Duration, value expiringCacheEn
|
||||
xe.timestamp = time.Now()
|
||||
xMux.Lock()
|
||||
xcache[key] = value
|
||||
count(key)
|
||||
xMux.Unlock()
|
||||
go xe.expire()
|
||||
}
|
||||
@@ -61,6 +68,7 @@ func (xe *XEntry) expire() {
|
||||
if !xe.keepAlive {
|
||||
xMux.Lock()
|
||||
delete(xcache, xe.key)
|
||||
descount(xe.key)
|
||||
xMux.Unlock()
|
||||
}
|
||||
}
|
||||
@@ -99,6 +107,7 @@ func Cache(key string, value interface{}) {
|
||||
mux.Lock()
|
||||
defer mux.Unlock()
|
||||
cache[key] = timestampedValue{time.Now(), value}
|
||||
count(key)
|
||||
}
|
||||
|
||||
// The function to extract a value for a key that never expire
|
||||
@@ -117,10 +126,6 @@ func GetKeyAge(key string) (time.Duration, error) {
|
||||
if r, ok := cache[key]; ok {
|
||||
return time.Since(r.timestamp), nil
|
||||
}
|
||||
return 0, errors.New("not found")
|
||||
}
|
||||
|
||||
func GetXKeyAge(key string) (time.Duration, error) {
|
||||
xMux.RLock()
|
||||
defer xMux.RUnlock()
|
||||
if r, ok := xcache[key]; ok {
|
||||
@@ -133,9 +138,6 @@ func RemKey(key string) {
|
||||
mux.Lock()
|
||||
defer mux.Unlock()
|
||||
delete(cache, key)
|
||||
}
|
||||
|
||||
func XRemKey(key string) {
|
||||
xMux.Lock()
|
||||
defer xMux.Unlock()
|
||||
if r, ok := xcache[key]; ok {
|
||||
@@ -144,6 +146,7 @@ func XRemKey(key string) {
|
||||
}
|
||||
}
|
||||
delete(xcache, key)
|
||||
descount(key)
|
||||
}
|
||||
|
||||
func RemPrefixKey(prefix string) {
|
||||
@@ -152,11 +155,9 @@ func RemPrefixKey(prefix string) {
|
||||
for key, _ := range cache {
|
||||
if strings.HasPrefix(key, prefix) {
|
||||
delete(cache, key)
|
||||
descount(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func XRemPrefixKey(prefix string) {
|
||||
xMux.Lock()
|
||||
defer xMux.Unlock()
|
||||
for key, _ := range xcache {
|
||||
@@ -167,6 +168,7 @@ func XRemPrefixKey(prefix string) {
|
||||
}
|
||||
}
|
||||
delete(xcache, key)
|
||||
descount(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -178,11 +180,6 @@ func GetAllEntries(prefix string) map[string]interface{} {
|
||||
result[key] = timestampedValue.value
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func XGetAllEntries(prefix string) map[string]interface{} {
|
||||
result := make(map[string]interface{})
|
||||
for key, value := range xcache {
|
||||
if strings.HasPrefix(key, prefix) {
|
||||
result[key] = value
|
||||
@@ -191,8 +188,8 @@ func XGetAllEntries(prefix string) map[string]interface{} {
|
||||
return result
|
||||
}
|
||||
|
||||
// Delete all keys from expiraton cache
|
||||
func XFlush() {
|
||||
// Delete all keys from cache
|
||||
func Flush() {
|
||||
xMux.Lock()
|
||||
defer xMux.Unlock()
|
||||
for _, v := range xcache {
|
||||
@@ -201,29 +198,44 @@ func XFlush() {
|
||||
}
|
||||
}
|
||||
xcache = make(map[string]expiringCacheEntry)
|
||||
}
|
||||
|
||||
// Delete all keys from cache
|
||||
func Flush() {
|
||||
mux.Lock()
|
||||
defer mux.Unlock()
|
||||
cache = make(map[string]timestampedValue)
|
||||
counters = make(map[string]int64)
|
||||
}
|
||||
|
||||
func CountEntries(prefix string) (result int) {
|
||||
for key, _ := range cache {
|
||||
if strings.HasPrefix(key, prefix) {
|
||||
result++
|
||||
}
|
||||
func CountEntries(prefix string) (result int64) {
|
||||
if _, ok := counters[prefix]; ok {
|
||||
return counters[prefix]
|
||||
}
|
||||
return
|
||||
return 0
|
||||
}
|
||||
|
||||
func XCountEntries(prefix string) (result int) {
|
||||
for key, _ := range xcache {
|
||||
if strings.HasPrefix(key, prefix) {
|
||||
result++
|
||||
}
|
||||
// increments the counter for the specified key prefix
|
||||
func count(key string) {
|
||||
if len(key) < PREFIX_LEN {
|
||||
return
|
||||
}
|
||||
cMux.Lock()
|
||||
defer cMux.Unlock()
|
||||
prefix := key[:PREFIX_LEN]
|
||||
if _, ok := counters[prefix]; ok {
|
||||
// increase the value
|
||||
counters[prefix] += 1
|
||||
} else {
|
||||
counters[prefix] = 1
|
||||
}
|
||||
}
|
||||
|
||||
// decrements the counter for the specified key prefix
|
||||
func descount(key string) {
|
||||
if len(key) < PREFIX_LEN {
|
||||
return
|
||||
}
|
||||
cMux.Lock()
|
||||
defer cMux.Unlock()
|
||||
prefix := key[:PREFIX_LEN]
|
||||
if _, ok := counters[prefix]; ok {
|
||||
counters[prefix] -= 1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ func TestFlush(t *testing.T) {
|
||||
a := &myStruct{data: "mama are mere"}
|
||||
a.XCache("mama", 10*time.Second, a)
|
||||
time.Sleep(1000 * time.Millisecond)
|
||||
XFlush()
|
||||
Flush()
|
||||
b, err := GetXCached("mama")
|
||||
if err == nil || b != nil {
|
||||
t.Error("Error expiring data")
|
||||
@@ -67,7 +67,7 @@ func TestFlush(t *testing.T) {
|
||||
func TestFlushNoTimout(t *testing.T) {
|
||||
a := &myStruct{data: "mama are mere"}
|
||||
a.XCache("mama", 10*time.Second, a)
|
||||
XFlush()
|
||||
Flush()
|
||||
b, err := GetXCached("mama")
|
||||
if err == nil || b != nil {
|
||||
t.Error("Error expiring data")
|
||||
@@ -91,7 +91,7 @@ func TestXRemKey(t *testing.T) {
|
||||
if t1, err := GetXCached("mama"); err != nil || t1 != a {
|
||||
t.Error("Error setting xcache")
|
||||
}
|
||||
XRemKey("mama")
|
||||
RemKey("mama")
|
||||
if t1, err := GetXCached("mama"); err == nil || t1 == a {
|
||||
t.Error("Error removing xcached key: ", err, t1)
|
||||
}
|
||||
@@ -134,10 +134,21 @@ func TestXRemPrefixKey(t *testing.T) {
|
||||
a.XCache("x_t1", 10*time.Second, a)
|
||||
a.XCache("y_t1", 10*time.Second, a)
|
||||
|
||||
XRemPrefixKey("x_")
|
||||
RemPrefixKey("x_")
|
||||
_, errX := GetXCached("x_t1")
|
||||
_, errY := GetXCached("y_t1")
|
||||
if errX == nil || errY != nil {
|
||||
t.Error("Error removing prefix: ", errX, errY)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCount(t *testing.T) {
|
||||
Cache("dst_A1", "1")
|
||||
Cache("dst_A2", "2")
|
||||
Cache("rpf_A3", "3")
|
||||
Cache("dst_A4", "4")
|
||||
Cache("dst_A5", "5")
|
||||
if CountEntries("dst_") != 4 {
|
||||
t.Error("Error countiong entries: ", CountEntries("dst_"))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user