diff --git a/cache2go/cache.go b/cache2go/cache.go index e4d9abc05..cb3bf66ee 100644 --- a/cache2go/cache.go +++ b/cache2go/cache.go @@ -11,6 +11,7 @@ import ( const ( PREFIX_LEN = 4 KIND_ADD = "ADD" + KIND_ADP = "ADP" KIND_REM = "REM" KIND_PRF = "PRF" ) @@ -63,6 +64,8 @@ func CommitTransaction() { RemPrefixKey(item.key) case KIND_ADD: Cache(item.key, item.value) + case KIND_ADP: + CachePush(item.key, item.value) } } mux.Unlock() @@ -83,11 +86,40 @@ func Cache(key string, value interface{}) { count(key) } cache[key] = timestampedValue{time.Now(), value} + //fmt.Println("ADD: ", key) } else { transactionBuffer = append(transactionBuffer, transactionItem{key: key, value: value, kind: KIND_ADD}) } } +// Appends to an existing slice in the cache key +func CachePush(key string, val interface{}) { + if !transactionLock { + mux.Lock() + defer mux.Unlock() + } + if !transactionON { + var elements []interface{} + if ti, exists := cache[key]; exists { + elements = ti.value.([]interface{}) + } + // check if the val is already present + found := false + for _, v := range elements { + if val == v { + found = true + break + } + } + if !found { + elements = append(elements, val) + } + cache[key] = timestampedValue{time.Now(), elements} + } else { + transactionBuffer = append(transactionBuffer, transactionItem{key: key, value: val, kind: KIND_ADP}) + } +} + // The function to extract a value for a key that never expire func GetCached(key string) (v interface{}, err error) { mux.RLock() @@ -114,6 +146,7 @@ func RemKey(key string) { } if !transactionON { if _, ok := cache[key]; ok { + //fmt.Println("REM: ", key) delete(cache, key) descount(key) } @@ -127,15 +160,16 @@ func RemPrefixKey(prefix string) { mux.Lock() defer mux.Unlock() } - for key, _ := range cache { - if !transactionON { + if !transactionON { + for key, _ := range cache { if strings.HasPrefix(key, prefix) { + //fmt.Println("PRF: ", key) delete(cache, key) descount(key) } } - } - if transactionON { + } else { + transactionBuffer = append(transactionBuffer, transactionItem{key: prefix, kind: KIND_PRF}) } } diff --git a/cache2go/cache_test.go b/cache2go/cache_test.go index 77a23f1f9..5e27e11c4 100644 --- a/cache2go/cache_test.go +++ b/cache2go/cache_test.go @@ -85,6 +85,15 @@ func TestRemPrefixKey(t *testing.T) { } } +func TestCachePush(t *testing.T) { + CachePush("x_t1", "1") + CachePush("x_t1", "2") + v, err := GetCached("x_t1") + if err != nil || len(v.([]interface{})) != 2 { + t.Error("Error in cache push: ", v) + } +} + func TestCount(t *testing.T) { Cache("dst_A1", "1") Cache("dst_A2", "2") diff --git a/engine/account.go b/engine/account.go index 39ff410dd..bfec3a4dd 100644 --- a/engine/account.go +++ b/engine/account.go @@ -160,7 +160,7 @@ func (ub *Account) getBalancesForPrefix(prefix, category string, balances Balanc if b.DestinationId != "" && b.DestinationId != utils.ANY { for _, p := range utils.SplitPrefix(prefix, MIN_PREFIX_MATCH) { if x, err := cache2go.GetCached(DESTINATION_PREFIX + p); err == nil { - destIds := x.([]string) + destIds := x.([]interface{}) for _, dId := range destIds { if dId == b.DestinationId { b.precision = len(p) diff --git a/engine/calldesc.go b/engine/calldesc.go index 9a2130b8b..d27e8e852 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -35,7 +35,7 @@ const ( RECURSION_MAX_DEPTH = 3 MIN_PREFIX_MATCH = 1 FALLBACK_SUBJECT = utils.ANY - DEBUG = false + DEBUG = true ) func init() { diff --git a/engine/destinations.go b/engine/destinations.go index caa42abbd..7604b12f7 100644 --- a/engine/destinations.go +++ b/engine/destinations.go @@ -75,7 +75,7 @@ func (d *Destination) GetHistoryRecord() history.Record { // Reverse search in cache to see if prefix belongs to destination id func CachedDestHasPrefix(destId, prefix string) bool { if cached, err := cache2go.GetCached(DESTINATION_PREFIX + prefix); err == nil { - for _, cachedDstId := range cached.([]string) { + for _, cachedDstId := range cached.([]interface{}) { if destId == cachedDstId { return true } @@ -87,10 +87,10 @@ func CachedDestHasPrefix(destId, prefix string) bool { func CleanStalePrefixes(destIds []string) { prefixMap := cache2go.GetAllEntries(DESTINATION_PREFIX) for prefix, idIDs := range prefixMap { - dIDs := idIDs.([]string) + dIDs := idIDs.([]interface{}) changed := false for _, searchedDID := range destIds { - if found, i := utils.GetSliceMemberIndex(dIDs, searchedDID); found { + if i, found := utils.GetSliceMemberIndex(utils.ConvertInterfaceSliceToStringSlice(dIDs), searchedDID); found { if len(dIDs) == 1 { // remove de prefix from cache cache2go.RemKey(prefix) diff --git a/engine/destinations_test.go b/engine/destinations_test.go index 2ae708c9e..9eed163b4 100644 --- a/engine/destinations_test.go +++ b/engine/destinations_test.go @@ -126,17 +126,17 @@ func TestNonCachedDestWrongPrefix(t *testing.T) { } func TestCleanStalePrefixes(t *testing.T) { - cache2go.Cache(DESTINATION_PREFIX+"1", []string{"D1", "D2"}) - cache2go.Cache(DESTINATION_PREFIX+"2", []string{"D1"}) - cache2go.Cache(DESTINATION_PREFIX+"3", []string{"D2"}) + cache2go.Cache(DESTINATION_PREFIX+"1", []interface{}{"D1", "D2"}) + cache2go.Cache(DESTINATION_PREFIX+"2", []interface{}{"D1"}) + cache2go.Cache(DESTINATION_PREFIX+"3", []interface{}{"D2"}) CleanStalePrefixes([]string{"D1"}) - if r, err := cache2go.GetCached(DESTINATION_PREFIX + "1"); err != nil || len(r.([]string)) != 1 { + if r, err := cache2go.GetCached(DESTINATION_PREFIX + "1"); err != nil || len(r.([]interface{})) != 1 { t.Error("Error cleaning stale destination ids", r) } if r, err := cache2go.GetCached(DESTINATION_PREFIX + "2"); err == nil { t.Error("Error removing stale prefix: ", r) } - if r, err := cache2go.GetCached(DESTINATION_PREFIX + "3"); err != nil || len(r.([]string)) != 1 { + if r, err := cache2go.GetCached(DESTINATION_PREFIX + "3"); err != nil || len(r.([]interface{})) != 1 { t.Error("Error performing stale cleaning: ", r) } } diff --git a/engine/handler_derivedcharging_test.go b/engine/handler_derivedcharging_test.go index e212e05dd..f58c78c5b 100644 --- a/engine/handler_derivedcharging_test.go +++ b/engine/handler_derivedcharging_test.go @@ -31,11 +31,7 @@ var acntDb AccountingStorage func init() { cfgDcT, _ = config.NewDefaultCGRConfig() - if DEBUG { - acntDb, _ = NewMapStorage() - } else { - acntDb, _ = NewRedisStorage("127.0.0.1:6379", 13, "", utils.MSGPACK) - } + acntDb = accountingStorage acntDb.CacheAccounting(nil, nil, nil, nil) } diff --git a/engine/ratingprofile.go b/engine/ratingprofile.go index 3af5202ec..3ec16692d 100644 --- a/engine/ratingprofile.go +++ b/engine/ratingprofile.go @@ -127,8 +127,9 @@ func (rp *RatingProfile) GetRatingPlansForPrefix(cd *CallDescriptor) (err error) } else { for _, p := range utils.SplitPrefix(cd.Destination, MIN_PREFIX_MATCH) { if x, err := cache2go.GetCached(DESTINATION_PREFIX + p); err == nil { - destIds := x.([]string) - for _, dId := range destIds { + destIds := x.([]interface{}) + for _, idId := range destIds { + dId := idId.(string) if _, ok := rpl.DestinationRates[dId]; ok { rps = rpl.RateIntervalList(dId) prefix = p diff --git a/engine/responder_test.go b/engine/responder_test.go index b5b1b5979..f0c7b60b7 100644 --- a/engine/responder_test.go +++ b/engine/responder_test.go @@ -40,6 +40,6 @@ func TestResponderGetDerivedChargers(t *testing.T) { t.Error("Unexpected error", err.Error()) } else if !reflect.DeepEqual(dcs, cfgedDC) { //t.Errorf("Expecting: %v, received: %v ", cfgedDC, dcs) - //TODO: fix the above test when DEBUG=false + //FIXME: fix the above test } } diff --git a/engine/storage_map.go b/engine/storage_map.go index 47fa19a1d..b27391ab9 100644 --- a/engine/storage_map.go +++ b/engine/storage_map.go @@ -53,6 +53,7 @@ func (ms *MapStorage) Flush() error { } func (ms *MapStorage) CacheRating(dKeys, rpKeys, rpfKeys, alsKeys, lcrKeys []string) error { + cache2go.BeginTransaction() if dKeys == nil { cache2go.RemPrefixKey(DESTINATION_PREFIX) } else { @@ -70,7 +71,6 @@ func (ms *MapStorage) CacheRating(dKeys, rpKeys, rpfKeys, alsKeys, lcrKeys []str if lcrKeys == nil { cache2go.RemPrefixKey(LCR_PREFIX) } - cache2go.BeginTransaction() for k, _ := range ms.dict { if strings.HasPrefix(k, DESTINATION_PREFIX) { if _, err := ms.GetDestination(k[len(DESTINATION_PREFIX):]); err != nil { @@ -172,13 +172,12 @@ func (ms *MapStorage) HasData(categ, subject string) (bool, error) { return false, errors.New("Unsupported category") } -func (ms *MapStorage) GetRatingPlan(key string, checkDb bool) (rp *RatingPlan, err error) { +func (ms *MapStorage) GetRatingPlan(key string, skipCache bool) (rp *RatingPlan, err error) { key = RATING_PLAN_PREFIX + key - if x, err := cache2go.GetCached(key); err == nil { - return x.(*RatingPlan), nil - } - if !checkDb { - return nil, errors.New(utils.ERR_NOT_FOUND) + if !skipCache { + if x, err := cache2go.GetCached(key); err == nil { + return x.(*RatingPlan), nil + } } if values, ok := ms.dict[key]; ok { b := bytes.NewBuffer(values) @@ -215,13 +214,12 @@ func (ms *MapStorage) SetRatingPlan(rp *RatingPlan) (err error) { return } -func (ms *MapStorage) GetRatingProfile(key string, checkDb bool) (rpf *RatingProfile, err error) { +func (ms *MapStorage) GetRatingProfile(key string, skipCache bool) (rpf *RatingProfile, err error) { key = RATING_PROFILE_PREFIX + key - if x, err := cache2go.GetCached(key); err == nil { - return x.(*RatingProfile), nil - } - if !checkDb { - return nil, errors.New(utils.ERR_NOT_FOUND) + if !skipCache { + if x, err := cache2go.GetCached(key); err == nil { + return x.(*RatingProfile), nil + } } if values, ok := ms.dict[key]; ok { rpf = new(RatingProfile) @@ -245,13 +243,12 @@ func (ms *MapStorage) SetRatingProfile(rpf *RatingProfile) (err error) { return } -func (ms *MapStorage) GetLCR(key string, checkDb bool) (lcr *LCR, err error) { +func (ms *MapStorage) GetLCR(key string, skipCache bool) (lcr *LCR, err error) { key = LCR_PREFIX + key - if x, err := cache2go.GetCached(key); err == nil { - return x.(*LCR), nil - } - if !checkDb { - return nil, errors.New(utils.ERR_NOT_FOUND) + if !skipCache { + if x, err := cache2go.GetCached(key); err == nil { + return x.(*LCR), nil + } } if values, ok := ms.dict[key]; ok { err = ms.ms.Unmarshal(values, &lcr) @@ -269,13 +266,12 @@ func (ms *MapStorage) SetLCR(lcr *LCR) (err error) { return } -func (ms *MapStorage) GetRpAlias(key string, checkDb bool) (alias string, err error) { +func (ms *MapStorage) GetRpAlias(key string, skipCache bool) (alias string, err error) { key = RP_ALIAS_PREFIX + key - if x, err := cache2go.GetCached(key); err == nil { - return x.(string), nil - } - if !checkDb { - return "", errors.New(utils.ERR_NOT_FOUND) + if !skipCache { + if x, err := cache2go.GetCached(key); err == nil { + return x.(string), nil + } } if values, ok := ms.dict[key]; ok { alias = string(values) @@ -311,18 +307,21 @@ func (ms *MapStorage) RemoveRpAliases(tenantRtSubjects []*TenantRatingSubject) ( return } -func (ms *MapStorage) GetRPAliases(tenant, subject string, checkDb bool) (aliases []string, err error) { +func (ms *MapStorage) GetRPAliases(tenant, subject string, skipCache bool) (aliases []string, err error) { tenantPrfx := RP_ALIAS_PREFIX + tenant + utils.CONCATENATED_KEY_SEP - alsKeys := cache2go.GetEntriesKeys(tenantPrfx) + var alsKeys []string + if !skipCache { + alsKeys = cache2go.GetEntriesKeys(tenantPrfx) + } for _, key := range alsKeys { - if alsSubj, err := ms.GetRpAlias(key[len(RP_ALIAS_PREFIX):], checkDb); err != nil { + if alsSubj, err := ms.GetRpAlias(key[len(RP_ALIAS_PREFIX):], skipCache); err != nil { return nil, err } else if alsSubj == subject { alsFromKey := key[len(tenantPrfx):] // take out the alias out of key+tenant aliases = append(aliases, alsFromKey) } } - if len(alsKeys) == 0 && checkDb { + if len(alsKeys) == 0 { for key, value := range ms.dict { if strings.HasPrefix(key, RP_ALIAS_PREFIX) && len(key) >= len(tenantPrfx) && key[:len(tenantPrfx)] == tenantPrfx && subject == string(value) { aliases = append(aliases, key[len(tenantPrfx):]) @@ -332,13 +331,12 @@ func (ms *MapStorage) GetRPAliases(tenant, subject string, checkDb bool) (aliase return aliases, nil } -func (ms *MapStorage) GetAccAlias(key string, checkDb bool) (alias string, err error) { +func (ms *MapStorage) GetAccAlias(key string, skipCache bool) (alias string, err error) { key = ACC_ALIAS_PREFIX + key - if x, err := cache2go.GetCached(key); err == nil { - return x.(string), nil - } - if !checkDb { - return "", errors.New(utils.ERR_NOT_FOUND) + if !skipCache { + if x, err := cache2go.GetCached(key); err == nil { + return x.(string), nil + } } if values, ok := ms.dict[key]; ok { alias = string(values) @@ -367,7 +365,7 @@ func (ms *MapStorage) RemoveAccAliases(tenantAccounts []*TenantAccount) (err err return } -func (ms *MapStorage) GetAccountAliases(tenant, account string, checkDb bool) (aliases []string, err error) { +func (ms *MapStorage) GetAccountAliases(tenant, account string, skipCache bool) (aliases []string, err error) { for key, value := range ms.dict { tenantPrfx := ACC_ALIAS_PREFIX + tenant + utils.CONCATENATED_KEY_SEP if strings.HasPrefix(key, ACC_ALIAS_PREFIX) && len(key) >= len(tenantPrfx) && key[:len(tenantPrfx)] == tenantPrfx && account == string(value) { @@ -394,14 +392,7 @@ func (ms *MapStorage) GetDestination(key string) (dest *Destination, err error) err = ms.ms.Unmarshal(out, dest) // create optimized structure for _, p := range dest.Prefixes { - var ids []string - if x, err := cache2go.GetCached(DESTINATION_PREFIX + p); err == nil { - ids = x.([]string) - } - if !utils.IsSliceMember(ids, dest.Id) { - ids = append(ids, dest.Id) - } - cache2go.Cache(DESTINATION_PREFIX+p, ids) + cache2go.CachePush(DESTINATION_PREFIX+p, dest.Id) } } else { return nil, errors.New("not found") @@ -424,13 +415,12 @@ func (ms *MapStorage) SetDestination(dest *Destination) (err error) { return } -func (ms *MapStorage) GetActions(key string, checkDb bool) (as Actions, err error) { +func (ms *MapStorage) GetActions(key string, skipCache bool) (as Actions, err error) { key = ACTION_PREFIX + key - if x, err := cache2go.GetCached(key); err == nil { - return x.(Actions), nil - } - if !checkDb { - return nil, errors.New(utils.ERR_NOT_FOUND) + if !skipCache { + if x, err := cache2go.GetCached(key); err == nil { + return x.(Actions), nil + } } if values, ok := ms.dict[key]; ok { err = ms.ms.Unmarshal(values, &as) @@ -448,13 +438,12 @@ func (ms *MapStorage) SetActions(key string, as Actions) (err error) { return } -func (ms *MapStorage) GetSharedGroup(key string, checkDb bool) (sg *SharedGroup, err error) { +func (ms *MapStorage) GetSharedGroup(key string, skipCache bool) (sg *SharedGroup, err error) { key = SHARED_GROUP_PREFIX + key - if x, err := cache2go.GetCached(key); err == nil { - return x.(*SharedGroup), nil - } - if !checkDb { - return nil, errors.New(utils.ERR_NOT_FOUND) + if !skipCache { + if x, err := cache2go.GetCached(key); err == nil { + return x.(*SharedGroup), nil + } } if values, ok := ms.dict[key]; ok { err = ms.ms.Unmarshal(values, &sg) @@ -529,13 +518,12 @@ func (ms *MapStorage) GetAllActionTimings() (ats map[string]ActionPlan, err erro return } -func (ms *MapStorage) GetDerivedChargers(key string, checkDb bool) (dcs utils.DerivedChargers, err error) { +func (ms *MapStorage) GetDerivedChargers(key string, skipCache bool) (dcs utils.DerivedChargers, err error) { key = DERIVEDCHARGERS_PREFIX + key - if x, err := cache2go.GetCached(key); err == nil { - return x.(utils.DerivedChargers), nil - } - if !checkDb { - return nil, errors.New(utils.ERR_NOT_FOUND) + if !skipCache { + if x, err := cache2go.GetCached(key); err == nil { + return x.(utils.DerivedChargers), nil + } } if values, ok := ms.dict[key]; ok { err = ms.ms.Unmarshal(values, &dcs) diff --git a/engine/storage_redis.go b/engine/storage_redis.go index 6e2b4d74b..2db45ba1d 100644 --- a/engine/storage_redis.go +++ b/engine/storage_redis.go @@ -67,7 +67,7 @@ func (rs *RedisStorage) Flush() (err error) { return } -func (rs *RedisStorage) CacheRating(dKeys, rpKeys, rpfKeys, alsKeys, lcrKeys []string) error { +func (rs *RedisStorage) CacheRating(dKeys, rpKeys, rpfKeys, alsKeys, lcrKeys []string) (err error) { cache2go.BeginTransaction() if dKeys == nil { Logger.Info("Caching all destinations") @@ -173,7 +173,7 @@ func (rs *RedisStorage) CacheRating(dKeys, rpKeys, rpfKeys, alsKeys, lcrKeys []s return nil } -func (rs *RedisStorage) CacheAccounting(actKeys, shgKeys, alsKeys, dcsKeys []string) error { +func (rs *RedisStorage) CacheAccounting(actKeys, shgKeys, alsKeys, dcsKeys []string) (err error) { cache2go.BeginTransaction() if actKeys == nil { cache2go.RemPrefixKey(ACTION_PREFIX) @@ -273,13 +273,12 @@ func (rs *RedisStorage) HasData(category, subject string) (bool, error) { return false, errors.New("Unsupported category in ExistsData") } -func (rs *RedisStorage) GetRatingPlan(key string, checkDb bool) (rp *RatingPlan, err error) { +func (rs *RedisStorage) GetRatingPlan(key string, skipCache bool) (rp *RatingPlan, err error) { key = RATING_PLAN_PREFIX + key - if x, err := cache2go.GetCached(key); err == nil { - return x.(*RatingPlan), nil - } - if !checkDb { - return nil, errors.New(utils.ERR_NOT_FOUND) + if !skipCache { + if x, err := cache2go.GetCached(key); err == nil { + return x.(*RatingPlan), nil + } } var values []byte if values, err = rs.db.Get(key); err == nil { @@ -315,13 +314,13 @@ func (rs *RedisStorage) SetRatingPlan(rp *RatingPlan) (err error) { return } -func (rs *RedisStorage) GetRatingProfile(key string, checkDb bool) (rpf *RatingProfile, err error) { +func (rs *RedisStorage) GetRatingProfile(key string, skipCache bool) (rpf *RatingProfile, err error) { + key = RATING_PROFILE_PREFIX + key - if x, err := cache2go.GetCached(key); err == nil { - return x.(*RatingProfile), nil - } - if !checkDb { - return nil, errors.New(utils.ERR_NOT_FOUND) + if !skipCache { + if x, err := cache2go.GetCached(key); err == nil { + return x.(*RatingProfile), nil + } } var values []byte if values, err = rs.db.Get(key); err == nil { @@ -343,14 +342,12 @@ func (rs *RedisStorage) SetRatingProfile(rpf *RatingProfile) (err error) { return } -func (rs *RedisStorage) GetRpAlias(key string, checkDb bool) (alias string, err error) { - +func (rs *RedisStorage) GetRpAlias(key string, skipCache bool) (alias string, err error) { key = RP_ALIAS_PREFIX + key - if x, err := cache2go.GetCached(key); err == nil { - return x.(string), nil - } - if !checkDb { - return "", errors.New(utils.ERR_NOT_FOUND) + if !skipCache { + if x, err := cache2go.GetCached(key); err == nil { + return x.(string), nil + } } var values []byte if values, err = rs.db.Get(key); err == nil { @@ -394,16 +391,19 @@ func (rs *RedisStorage) RemoveRpAliases(tenantRtSubjects []*TenantRatingSubject) return } -func (rs *RedisStorage) GetRPAliases(tenant, subject string, checkDb bool) (aliases []string, err error) { +func (rs *RedisStorage) GetRPAliases(tenant, subject string, skipCache bool) (aliases []string, err error) { tenantPrfx := RP_ALIAS_PREFIX + tenant + utils.CONCATENATED_KEY_SEP - alsKeys := cache2go.GetEntriesKeys(tenantPrfx) - if len(alsKeys) == 0 && checkDb { + var alsKeys []string + if !skipCache { + alsKeys = cache2go.GetEntriesKeys(tenantPrfx) + } + if len(alsKeys) == 0 { if alsKeys, err = rs.db.Keys(tenantPrfx + "*"); err != nil { return nil, err } } for _, key := range alsKeys { - if alsSubj, err := rs.GetRpAlias(key[len(RP_ALIAS_PREFIX):], checkDb); err != nil { + if alsSubj, err := rs.GetRpAlias(key[len(RP_ALIAS_PREFIX):], skipCache); err != nil { return nil, err } else if alsSubj == subject { alsFromKey := key[len(tenantPrfx):] // take out the alias out of key+tenant @@ -413,13 +413,12 @@ func (rs *RedisStorage) GetRPAliases(tenant, subject string, checkDb bool) (alia return aliases, nil } -func (rs *RedisStorage) GetLCR(key string, checkDb bool) (lcr *LCR, err error) { +func (rs *RedisStorage) GetLCR(key string, skipCache bool) (lcr *LCR, err error) { key = LCR_PREFIX + key - if x, err := cache2go.GetCached(key); err == nil { - return x.(*LCR), nil - } - if !checkDb { - return nil, errors.New(utils.ERR_NOT_FOUND) + if !skipCache { + if x, err := cache2go.GetCached(key); err == nil { + return x.(*LCR), nil + } } var values []byte if values, err = rs.db.Get(key); err == nil { @@ -436,13 +435,12 @@ func (rs *RedisStorage) SetLCR(lcr *LCR) (err error) { return } -func (rs *RedisStorage) GetAccAlias(key string, checkDb bool) (alias string, err error) { +func (rs *RedisStorage) GetAccAlias(key string, skipCache bool) (alias string, err error) { key = ACC_ALIAS_PREFIX + key - if x, err := cache2go.GetCached(key); err == nil { - return x.(string), nil - } - if !checkDb { - return "", errors.New(utils.ERR_NOT_FOUND) + if !skipCache { + if x, err := cache2go.GetCached(key); err == nil { + return x.(string), nil + } } var values []byte if values, err = rs.db.Get(key); err == nil { @@ -486,17 +484,20 @@ func (rs *RedisStorage) RemoveAccAliases(tenantAccounts []*TenantAccount) (err e } // Returns the aliases of one specific account on a tenant -func (rs *RedisStorage) GetAccountAliases(tenant, account string, checkDb bool) (aliases []string, err error) { +func (rs *RedisStorage) GetAccountAliases(tenant, account string, skipCache bool) (aliases []string, err error) { tenantPrfx := ACC_ALIAS_PREFIX + tenant + utils.CONCATENATED_KEY_SEP - alsKeys := cache2go.GetEntriesKeys(tenantPrfx) - if len(alsKeys) == 0 && checkDb { + var alsKeys []string + if !skipCache { + alsKeys = cache2go.GetEntriesKeys(tenantPrfx) + } + if len(alsKeys) == 0 { if alsKeys, err = rs.db.Keys(tenantPrfx + "*"); err != nil { return nil, err } } for _, key := range alsKeys { tenantPrfx := ACC_ALIAS_PREFIX + tenant + utils.CONCATENATED_KEY_SEP - if alsAcnt, err := rs.GetAccAlias(key[len(ACC_ALIAS_PREFIX):], checkDb); err != nil { + if alsAcnt, err := rs.GetAccAlias(key[len(ACC_ALIAS_PREFIX):], skipCache); err != nil { return nil, err } else if alsAcnt == account { alsFromKey := key[len(tenantPrfx):] // take out the alias out of key+tenant @@ -524,14 +525,7 @@ func (rs *RedisStorage) GetDestination(key string) (dest *Destination, err error err = rs.ms.Unmarshal(out, dest) // create optimized structure for _, p := range dest.Prefixes { - var ids []string - if x, err := cache2go.GetCached(DESTINATION_PREFIX + p); err == nil { - ids = x.([]string) - } - if !utils.IsSliceMember(ids, dest.Id) { - ids = append(ids, dest.Id) - } - cache2go.Cache(DESTINATION_PREFIX+p, ids) + cache2go.CachePush(DESTINATION_PREFIX+p, dest.Id) } } else { return nil, errors.New("not found") @@ -557,13 +551,12 @@ func (rs *RedisStorage) SetDestination(dest *Destination) (err error) { return } -func (rs *RedisStorage) GetActions(key string, checkDb bool) (as Actions, err error) { +func (rs *RedisStorage) GetActions(key string, skipCache bool) (as Actions, err error) { key = ACTION_PREFIX + key - if x, err := cache2go.GetCached(key); err == nil { - return x.(Actions), nil - } - if !checkDb { - return nil, errors.New(utils.ERR_NOT_FOUND) + if !skipCache { + if x, err := cache2go.GetCached(key); err == nil { + return x.(Actions), nil + } } var values []byte if values, err = rs.db.Get(key); err == nil { @@ -580,13 +573,12 @@ func (rs *RedisStorage) SetActions(key string, as Actions) (err error) { return } -func (rs *RedisStorage) GetSharedGroup(key string, checkDb bool) (sg *SharedGroup, err error) { +func (rs *RedisStorage) GetSharedGroup(key string, skipCache bool) (sg *SharedGroup, err error) { key = SHARED_GROUP_PREFIX + key - if x, err := cache2go.GetCached(key); err == nil { - return x.(*SharedGroup), nil - } - if !checkDb { - return nil, errors.New(utils.ERR_NOT_FOUND) + if !skipCache { + if x, err := cache2go.GetCached(key); err == nil { + return x.(*SharedGroup), nil + } } var values []byte if values, err = rs.db.Get(key); err == nil { @@ -599,7 +591,7 @@ func (rs *RedisStorage) GetSharedGroup(key string, checkDb bool) (sg *SharedGrou func (rs *RedisStorage) SetSharedGroup(sg *SharedGroup) (err error) { result, err := rs.ms.Marshal(sg) err = rs.db.Set(SHARED_GROUP_PREFIX+sg.Id, result) - cache2go.Cache(SHARED_GROUP_PREFIX+sg.Id, sg) + //cache2go.Cache(SHARED_GROUP_PREFIX+sg.Id, sg) return } @@ -664,13 +656,12 @@ func (rs *RedisStorage) GetAllActionTimings() (ats map[string]ActionPlan, err er return } -func (rs *RedisStorage) GetDerivedChargers(key string, checkDb bool) (dcs utils.DerivedChargers, err error) { +func (rs *RedisStorage) GetDerivedChargers(key string, skipCache bool) (dcs utils.DerivedChargers, err error) { key = DERIVEDCHARGERS_PREFIX + key - if x, err := cache2go.GetCached(key); err == nil { - return x.(utils.DerivedChargers), nil - } - if !checkDb { - return nil, errors.New(utils.ERR_NOT_FOUND) + if !skipCache { + if x, err := cache2go.GetCached(key); err == nil { + return x.(utils.DerivedChargers), nil + } } var values []byte if values, err = rs.db.Get(key); err == nil { @@ -683,6 +674,7 @@ func (rs *RedisStorage) GetDerivedChargers(key string, checkDb bool) (dcs utils. func (rs *RedisStorage) SetDerivedChargers(key string, dcs utils.DerivedChargers) (err error) { if len(dcs) == 0 { _, err = rs.db.Del(DERIVEDCHARGERS_PREFIX + key) + // FIXME: Does cache need cleanup too? return err } marshaled, err := rs.ms.Marshal(dcs) diff --git a/engine/storage_test.go b/engine/storage_test.go index 2f6501740..f2bc6c413 100644 --- a/engine/storage_test.go +++ b/engine/storage_test.go @@ -104,6 +104,7 @@ func TestCacheRefresh(t *testing.T) { dataStorage.SetDestination(&Destination{"T11", []string{"0"}}) dataStorage.GetDestination("T11") dataStorage.SetDestination(&Destination{"T11", []string{"1"}}) + t.Log("Test cache refresh") dataStorage.CacheRating(nil, nil, nil, nil, nil) d, err := dataStorage.GetDestination("T11") p := d.containsPrefix("1") diff --git a/engine/units_counter.go b/engine/units_counter.go index 879e8699c..ab975a28f 100644 --- a/engine/units_counter.go +++ b/engine/units_counter.go @@ -78,7 +78,7 @@ func (uc *UnitsCounter) addUnits(amount float64, prefix string) { } for _, p := range utils.SplitPrefix(prefix, MIN_PREFIX_MATCH) { if x, err := cache2go.GetCached(DESTINATION_PREFIX + p); err == nil { - destIds := x.([]string) + destIds := x.([]interface{}) for _, dId := range destIds { if dId == mb.DestinationId { mb.Value += amount diff --git a/utils/slice.go b/utils/slice.go index 5465adb98..d0bde4d28 100644 --- a/utils/slice.go +++ b/utils/slice.go @@ -34,12 +34,12 @@ func IsSliceMember(ss []string, s string) bool { // Binary string search in slice // returns true if found and the index -func GetSliceMemberIndex(ss []string, s string) (bool, int) { +func GetSliceMemberIndex(ss []string, s string) (int, bool) { sort.Strings(ss) if i := sort.SearchStrings(ss, s); i < len(ss) && ss[i] == s { - return true, i + return i, true } - return false, len(ss) + return len(ss), false } //Iterates over slice members and returns true if one starts with prefix @@ -51,3 +51,10 @@ func SliceMemberHasPrefix(ss []string, prfx string) bool { } return false } + +func ConvertInterfaceSliceToStringSlice(is []interface{}) (result []string) { + for _, i := range is { + result = append(result, i.(string)) + } + return result +}