mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-12 02:26:26 +05:00
200 lines
4.0 KiB
Go
200 lines
4.0 KiB
Go
//Simple caching library with expiration capabilities
|
|
package engine
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/cgrates/cgrates/utils"
|
|
)
|
|
|
|
const (
|
|
PREFIX_LEN = 4
|
|
KIND_ADD = "ADD"
|
|
KIND_ADP = "ADP"
|
|
KIND_REM = "REM"
|
|
KIND_POP = "POP"
|
|
KIND_PRF = "PRF"
|
|
DOUBLE_CACHE = true
|
|
)
|
|
|
|
var (
|
|
mux sync.RWMutex
|
|
cache cacheStore
|
|
// transaction stuff
|
|
transactionBuffer []*transactionItem
|
|
transactionMux sync.Mutex
|
|
transactionON = false
|
|
transactionLock = false
|
|
)
|
|
|
|
type transactionItem struct {
|
|
key string
|
|
value interface{}
|
|
kind string
|
|
}
|
|
|
|
func init() {
|
|
if DOUBLE_CACHE {
|
|
cache = newDoubleStore()
|
|
} else {
|
|
cache = newSimpleStore()
|
|
}
|
|
}
|
|
|
|
func CacheBeginTransaction() {
|
|
transactionMux.Lock()
|
|
transactionLock = true
|
|
transactionON = true
|
|
}
|
|
|
|
func CacheRollbackTransaction() {
|
|
transactionBuffer = nil
|
|
transactionLock = false
|
|
transactionON = false
|
|
transactionMux.Unlock()
|
|
}
|
|
|
|
func CacheCommitTransaction() {
|
|
transactionON = false
|
|
// apply all transactioned items
|
|
mux.Lock()
|
|
for _, item := range transactionBuffer {
|
|
switch item.kind {
|
|
case KIND_REM:
|
|
CacheRemKey(item.key)
|
|
case KIND_PRF:
|
|
CacheRemPrefixKey(item.key)
|
|
case KIND_ADD:
|
|
CacheSet(item.key, item.value)
|
|
case KIND_ADP:
|
|
CachePush(item.key, item.value.(string))
|
|
case KIND_POP:
|
|
CachePop(item.key, item.value.(string))
|
|
}
|
|
}
|
|
mux.Unlock()
|
|
transactionBuffer = nil
|
|
transactionLock = false
|
|
transactionMux.Unlock()
|
|
}
|
|
|
|
func CacheSave(path string, keys []string, cfi *utils.CacheFileInfo) error {
|
|
mux.Lock()
|
|
defer mux.Unlock()
|
|
return cache.Save(path, keys, cfi)
|
|
}
|
|
|
|
func CacheLoad(path string, keys []string) error {
|
|
start := time.Now()
|
|
if !transactionLock {
|
|
mux.Lock()
|
|
defer mux.Unlock()
|
|
}
|
|
if !transactionON {
|
|
return cache.Load(path, keys)
|
|
}
|
|
utils.Logger.Info(fmt.Sprintf("Cache rating load time: %v", time.Since(start)))
|
|
return nil
|
|
}
|
|
|
|
// The function to be used to cache a key/value pair when expiration is not needed
|
|
func CacheSet(key string, value interface{}) {
|
|
if !transactionLock {
|
|
mux.Lock()
|
|
defer mux.Unlock()
|
|
}
|
|
if !transactionON {
|
|
cache.Put(key, value)
|
|
//log.Println("ADD: ", key)
|
|
} else {
|
|
transactionBuffer = append(transactionBuffer, &transactionItem{key: key, value: value, kind: KIND_ADD})
|
|
}
|
|
}
|
|
|
|
// The function to extract a value for a key that never expire
|
|
func CacheGet(key string) (v interface{}, err error) {
|
|
mux.RLock()
|
|
defer mux.RUnlock()
|
|
return cache.Get(key)
|
|
}
|
|
|
|
// Appends to an existing slice in the cache key
|
|
func CachePush(key string, value string) {
|
|
if !transactionLock {
|
|
mux.Lock()
|
|
defer mux.Unlock()
|
|
}
|
|
if !transactionON {
|
|
cache.Append(key, value)
|
|
} else {
|
|
transactionBuffer = append(transactionBuffer, &transactionItem{key: key, value: value, kind: KIND_ADP})
|
|
}
|
|
}
|
|
|
|
func CachePop(key string, value string) {
|
|
if !transactionLock {
|
|
mux.Lock()
|
|
defer mux.Unlock()
|
|
}
|
|
if !transactionON {
|
|
cache.Pop(key, value)
|
|
} else {
|
|
transactionBuffer = append(transactionBuffer, &transactionItem{key: key, value: value, kind: KIND_POP})
|
|
}
|
|
}
|
|
|
|
func CacheRemKey(key string) {
|
|
if !transactionLock {
|
|
mux.Lock()
|
|
defer mux.Unlock()
|
|
}
|
|
if !transactionON {
|
|
cache.Delete(key)
|
|
} else {
|
|
transactionBuffer = append(transactionBuffer, &transactionItem{key: key, kind: KIND_REM})
|
|
}
|
|
}
|
|
|
|
func CacheRemPrefixKey(prefix string) {
|
|
if !transactionLock {
|
|
mux.Lock()
|
|
defer mux.Unlock()
|
|
}
|
|
if !transactionON {
|
|
cache.DeletePrefix(prefix)
|
|
} else {
|
|
transactionBuffer = append(transactionBuffer, &transactionItem{key: prefix, kind: KIND_PRF})
|
|
}
|
|
}
|
|
|
|
// Delete all keys from cache
|
|
func CacheFlush() {
|
|
mux.Lock()
|
|
defer mux.Unlock()
|
|
if DOUBLE_CACHE {
|
|
cache = newDoubleStore()
|
|
} else {
|
|
cache = newSimpleStore()
|
|
}
|
|
}
|
|
|
|
func CacheCountEntries(prefix string) (result int) {
|
|
mux.RLock()
|
|
defer mux.RUnlock()
|
|
return cache.CountEntriesForPrefix(prefix)
|
|
}
|
|
|
|
func CacheGetAllEntries(prefix string) (map[string]interface{}, error) {
|
|
mux.RLock()
|
|
defer mux.RUnlock()
|
|
return cache.GetAllForPrefix(prefix)
|
|
}
|
|
|
|
func CacheGetEntriesKeys(prefix string) (keys []string) {
|
|
mux.RLock()
|
|
defer mux.RUnlock()
|
|
return cache.GetKeysForPrefix(prefix)
|
|
}
|