diff --git a/cache/cache_store.go b/cache/cache_store.go index 16c32af46..39714fd2e 100755 --- a/cache/cache_store.go +++ b/cache/cache_store.go @@ -39,7 +39,7 @@ type cacheLRUTTL map[string]*ltcache.Cache func newLRUTTL(cfg config.CacheConfig) (c cacheLRUTTL) { c = map[string]*ltcache.Cache{ - utils.ANY: ltcache.New(0, 0, false, nil), // no limits for default cache instance + utils.ANY: ltcache.New(ltcache.UnlimitedCaching, ltcache.UnlimitedCaching, false, nil), // no limits for default cache instance } if cfg == nil { return diff --git a/config/config_defaults.go b/config/config_defaults.go index 635cd5883..27261f56a 100755 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -50,22 +50,22 @@ const CGRATES_CFG_JSON = ` "cache":{ - "destinations": {"limit": 0, "ttl": "0s", "static_ttl": false, "precache": false}, // control destination caching - "reverse_destinations": {"limit": 0, "ttl": "0s", "static_ttl": false, "precache": false}, // control reverse destinations index caching - "rating_plans": {"limit": 0, "ttl": "0s", "static_ttl": false, "precache": false}, // control rating plans caching - "rating_profiles": {"limit": 0, "ttl": "0s", "static_ttl": false, "precache": false}, // control rating profiles caching - "lcr_rules": {"limit": 0, "ttl": "0s", "static_ttl": false, "precache": false}, // control lcr rules caching - "cdr_stats": {"limit": 0, "ttl": "0s", "static_ttl": false, "precache": false}, // control cdr stats queues caching - "actions": {"limit": 0, "ttl": "0s", "static_ttl": false, "precache": false}, // control actions caching - "action_plans": {"limit": 0, "ttl": "0s", "static_ttl": false, "precache": false}, // control action plans caching - "account_action_plans": {"limit": 0, "ttl": "0s", "static_ttl": false, "precache": false}, // control account action plans index caching - "action_triggers": {"limit": 0, "ttl": "0s", "static_ttl": false, "precache": false}, // control action triggers caching - "shared_groups": {"limit": 0, "ttl": "0s", "static_ttl": false, "precache": false}, // control shared groups caching - "aliases": {"limit": 0, "ttl": "0s", "static_ttl": false, "precache": false}, // control aliases caching - "reverse_aliases": {"limit": 0, "ttl": "0s", "static_ttl": false, "precache": false}, // control reverse aliases index caching - "derived_chargers": {"limit": 0, "ttl": "0s", "static_ttl": false, "precache": false}, // control derived charging rule caching - "resource_configs": {"limit": 0, "ttl": "0s", "static_ttl": false, "precache": false}, // control resource caching - "timings": {"limit": 0, "ttl": "0s", "static_ttl": false, "precache": false}, // control timings caching + "destinations": {"limit": -1, "ttl": "", "static_ttl": false, "precache": false}, // control destination caching + "reverse_destinations": {"limit": -1, "ttl": "", "static_ttl": false, "precache": false}, // control reverse destinations index caching + "rating_plans": {"limit": -1, "ttl": "", "static_ttl": false, "precache": false}, // control rating plans caching + "rating_profiles": {"limit": -1, "ttl": "", "static_ttl": false, "precache": false}, // control rating profiles caching + "lcr_rules": {"limit": -1, "ttl": "", "static_ttl": false, "precache": false}, // control lcr rules caching + "cdr_stats": {"limit": -1, "ttl": "", "static_ttl": false, "precache": false}, // control cdr stats queues caching + "actions": {"limit": -1, "ttl": "", "static_ttl": false, "precache": false}, // control actions caching + "action_plans": {"limit": -1, "ttl": "", "static_ttl": false, "precache": false}, // control action plans caching + "account_action_plans": {"limit": -1, "ttl": "", "static_ttl": false, "precache": false}, // control account action plans index caching + "action_triggers": {"limit": -1, "ttl": "", "static_ttl": false, "precache": false}, // control action triggers caching + "shared_groups": {"limit": -1, "ttl": "", "static_ttl": false, "precache": false}, // control shared groups caching + "aliases": {"limit": -1, "ttl": "", "static_ttl": false, "precache": false}, // control aliases caching + "reverse_aliases": {"limit": -1, "ttl": "", "static_ttl": false, "precache": false}, // control reverse aliases index caching + "derived_chargers": {"limit": -1, "ttl": "", "static_ttl": false, "precache": false}, // control derived charging rule caching + "resource_configs": {"limit": -1, "ttl": "", "static_ttl": false, "precache": false}, // control resource configs caching + "timings": {"limit": -1, "ttl": "", "static_ttl": false, "precache": false}, // control timings caching }, diff --git a/config/config_json_test.go b/config/config_json_test.go index fadb6db0a..924ceccf2 100755 --- a/config/config_json_test.go +++ b/config/config_json_test.go @@ -67,53 +67,53 @@ func TestDfGeneralJsonCfg(t *testing.T) { func TestCacheJsonCfg(t *testing.T) { eCfg := &CacheJsonCfg{ - utils.CacheDestinations: &CacheParamJsonCfg{Limit: utils.IntPointer(0), - Ttl: utils.StringPointer("0s"), Static_ttl: utils.BoolPointer(false), + utils.CacheDestinations: &CacheParamJsonCfg{Limit: utils.IntPointer(-1), + Ttl: utils.StringPointer(""), Static_ttl: utils.BoolPointer(false), Precache: utils.BoolPointer(false)}, - utils.CacheReverseDestinations: &CacheParamJsonCfg{Limit: utils.IntPointer(0), - Ttl: utils.StringPointer("0s"), Static_ttl: utils.BoolPointer(false), + utils.CacheReverseDestinations: &CacheParamJsonCfg{Limit: utils.IntPointer(-1), + Ttl: utils.StringPointer(""), Static_ttl: utils.BoolPointer(false), Precache: utils.BoolPointer(false)}, - utils.CacheRatingPlans: &CacheParamJsonCfg{Limit: utils.IntPointer(0), - Ttl: utils.StringPointer("0s"), Static_ttl: utils.BoolPointer(false), + utils.CacheRatingPlans: &CacheParamJsonCfg{Limit: utils.IntPointer(-1), + Ttl: utils.StringPointer(""), Static_ttl: utils.BoolPointer(false), Precache: utils.BoolPointer(false)}, - utils.CacheRatingProfiles: &CacheParamJsonCfg{Limit: utils.IntPointer(0), - Ttl: utils.StringPointer("0s"), Static_ttl: utils.BoolPointer(false), + utils.CacheRatingProfiles: &CacheParamJsonCfg{Limit: utils.IntPointer(-1), + Ttl: utils.StringPointer(""), Static_ttl: utils.BoolPointer(false), Precache: utils.BoolPointer(false)}, - utils.CacheLCRRules: &CacheParamJsonCfg{Limit: utils.IntPointer(0), - Ttl: utils.StringPointer("0s"), Static_ttl: utils.BoolPointer(false), + utils.CacheLCRRules: &CacheParamJsonCfg{Limit: utils.IntPointer(-1), + Ttl: utils.StringPointer(""), Static_ttl: utils.BoolPointer(false), Precache: utils.BoolPointer(false)}, - utils.CacheCDRStatS: &CacheParamJsonCfg{Limit: utils.IntPointer(0), - Ttl: utils.StringPointer("0s"), Static_ttl: utils.BoolPointer(false), + utils.CacheCDRStatS: &CacheParamJsonCfg{Limit: utils.IntPointer(-1), + Ttl: utils.StringPointer(""), Static_ttl: utils.BoolPointer(false), Precache: utils.BoolPointer(false)}, - utils.CacheActions: &CacheParamJsonCfg{Limit: utils.IntPointer(0), - Ttl: utils.StringPointer("0s"), Static_ttl: utils.BoolPointer(false), + utils.CacheActions: &CacheParamJsonCfg{Limit: utils.IntPointer(-1), + Ttl: utils.StringPointer(""), Static_ttl: utils.BoolPointer(false), Precache: utils.BoolPointer(false)}, - utils.CacheActionPlans: &CacheParamJsonCfg{Limit: utils.IntPointer(0), - Ttl: utils.StringPointer("0s"), Static_ttl: utils.BoolPointer(false), + utils.CacheActionPlans: &CacheParamJsonCfg{Limit: utils.IntPointer(-1), + Ttl: utils.StringPointer(""), Static_ttl: utils.BoolPointer(false), Precache: utils.BoolPointer(false)}, - utils.CacheAccountActionPlans: &CacheParamJsonCfg{Limit: utils.IntPointer(0), - Ttl: utils.StringPointer("0s"), Static_ttl: utils.BoolPointer(false), + utils.CacheAccountActionPlans: &CacheParamJsonCfg{Limit: utils.IntPointer(-1), + Ttl: utils.StringPointer(""), Static_ttl: utils.BoolPointer(false), Precache: utils.BoolPointer(false)}, - utils.CacheActionTriggers: &CacheParamJsonCfg{Limit: utils.IntPointer(0), - Ttl: utils.StringPointer("0s"), Static_ttl: utils.BoolPointer(false), + utils.CacheActionTriggers: &CacheParamJsonCfg{Limit: utils.IntPointer(-1), + Ttl: utils.StringPointer(""), Static_ttl: utils.BoolPointer(false), Precache: utils.BoolPointer(false)}, - utils.CacheSharedGroups: &CacheParamJsonCfg{Limit: utils.IntPointer(0), - Ttl: utils.StringPointer("0s"), Static_ttl: utils.BoolPointer(false), + utils.CacheSharedGroups: &CacheParamJsonCfg{Limit: utils.IntPointer(-1), + Ttl: utils.StringPointer(""), Static_ttl: utils.BoolPointer(false), Precache: utils.BoolPointer(false)}, - utils.CacheAliases: &CacheParamJsonCfg{Limit: utils.IntPointer(0), - Ttl: utils.StringPointer("0s"), Static_ttl: utils.BoolPointer(false), + utils.CacheAliases: &CacheParamJsonCfg{Limit: utils.IntPointer(-1), + Ttl: utils.StringPointer(""), Static_ttl: utils.BoolPointer(false), Precache: utils.BoolPointer(false)}, - utils.CacheReverseAliases: &CacheParamJsonCfg{Limit: utils.IntPointer(0), - Ttl: utils.StringPointer("0s"), Static_ttl: utils.BoolPointer(false), + utils.CacheReverseAliases: &CacheParamJsonCfg{Limit: utils.IntPointer(-1), + Ttl: utils.StringPointer(""), Static_ttl: utils.BoolPointer(false), Precache: utils.BoolPointer(false)}, - utils.CacheDerivedChargers: &CacheParamJsonCfg{Limit: utils.IntPointer(0), - Ttl: utils.StringPointer("0s"), Static_ttl: utils.BoolPointer(false), + utils.CacheDerivedChargers: &CacheParamJsonCfg{Limit: utils.IntPointer(-1), + Ttl: utils.StringPointer(""), Static_ttl: utils.BoolPointer(false), Precache: utils.BoolPointer(false)}, - utils.CacheResourceConfigs: &CacheParamJsonCfg{Limit: utils.IntPointer(0), - Ttl: utils.StringPointer("0s"), Static_ttl: utils.BoolPointer(false), + utils.CacheResourceConfigs: &CacheParamJsonCfg{Limit: utils.IntPointer(-1), + Ttl: utils.StringPointer(""), Static_ttl: utils.BoolPointer(false), Precache: utils.BoolPointer(false)}, - utils.CacheTimings: &CacheParamJsonCfg{Limit: utils.IntPointer(0), - Ttl: utils.StringPointer("0s"), Static_ttl: utils.BoolPointer(false), + utils.CacheTimings: &CacheParamJsonCfg{Limit: utils.IntPointer(-1), + Ttl: utils.StringPointer(""), Static_ttl: utils.BoolPointer(false), Precache: utils.BoolPointer(false)}, } diff --git a/config/config_test.go b/config/config_test.go index f927596a5..75b4ac6e4 100755 --- a/config/config_test.go +++ b/config/config_test.go @@ -49,7 +49,10 @@ func TestCgrCfgLoadWithDefaults(t *testing.T) { }, }` - eCgrCfg, _ := NewDefaultCGRConfig() + eCgrCfg, err := NewDefaultCGRConfig() + if err != nil { + t.Error(err) + } eCgrCfg.SmFsConfig.Enabled = true eCgrCfg.SmFsConfig.EventSocketConns = []*FsConnConfig{ &FsConnConfig{Address: "1.2.3.4:8021", Password: "ClueCon", Reconnects: 3}, @@ -404,41 +407,41 @@ func TestCgrCfgJSONDefaultsSMGenericCfg(t *testing.T) { } func TestCgrCfgJSONDefaultsCacheCFG(t *testing.T) { eCacheCfg := CacheConfig{ - utils.CacheDestinations: &CacheParamConfig{Limit: 0, - TTL: time.Duration(0 * time.Second), StaticTTL: false, Precache: false}, - utils.CacheReverseDestinations: &CacheParamConfig{Limit: 0, - TTL: time.Duration(0 * time.Second), StaticTTL: false, Precache: false}, - utils.CacheRatingPlans: &CacheParamConfig{Limit: 0, - TTL: time.Duration(0 * time.Second), StaticTTL: false, Precache: false}, - utils.CacheRatingProfiles: &CacheParamConfig{Limit: 0, - TTL: time.Duration(0 * time.Second), StaticTTL: false, Precache: false}, - utils.CacheLCRRules: &CacheParamConfig{Limit: 0, - TTL: time.Duration(0 * time.Second), StaticTTL: false, Precache: false}, - utils.CacheCDRStatS: &CacheParamConfig{Limit: 0, - TTL: time.Duration(0 * time.Second), StaticTTL: false, Precache: false}, - utils.CacheActions: &CacheParamConfig{Limit: 0, - TTL: time.Duration(0 * time.Second), StaticTTL: false, Precache: false}, - utils.CacheActionPlans: &CacheParamConfig{Limit: 0, - TTL: time.Duration(0 * time.Second), StaticTTL: false, Precache: false}, - utils.CacheAccountActionPlans: &CacheParamConfig{Limit: 0, - TTL: time.Duration(0 * time.Second), StaticTTL: false, Precache: false}, - utils.CacheActionTriggers: &CacheParamConfig{Limit: 0, - TTL: time.Duration(0 * time.Second), StaticTTL: false, Precache: false}, - utils.CacheSharedGroups: &CacheParamConfig{Limit: 0, - TTL: time.Duration(0 * time.Second), StaticTTL: false, Precache: false}, - utils.CacheAliases: &CacheParamConfig{Limit: 0, - TTL: time.Duration(0 * time.Second), StaticTTL: false, Precache: false}, - utils.CacheReverseAliases: &CacheParamConfig{Limit: 0, - TTL: time.Duration(0 * time.Second), StaticTTL: false, Precache: false}, - utils.CacheDerivedChargers: &CacheParamConfig{Limit: 0, - TTL: time.Duration(0 * time.Second), StaticTTL: false, Precache: false}, - utils.CacheResourceConfigs: &CacheParamConfig{Limit: 0, - TTL: time.Duration(0 * time.Second), StaticTTL: false, Precache: false}, - utils.CacheTimings: &CacheParamConfig{Limit: 0, - TTL: time.Duration(0 * time.Second), StaticTTL: false, Precache: false}, + utils.CacheDestinations: &CacheParamConfig{Limit: -1, + TTL: time.Duration(0), StaticTTL: false, Precache: false}, + utils.CacheReverseDestinations: &CacheParamConfig{Limit: -1, + TTL: time.Duration(0), StaticTTL: false, Precache: false}, + utils.CacheRatingPlans: &CacheParamConfig{Limit: -1, + TTL: time.Duration(0), StaticTTL: false, Precache: false}, + utils.CacheRatingProfiles: &CacheParamConfig{Limit: -1, + TTL: time.Duration(0), StaticTTL: false, Precache: false}, + utils.CacheLCRRules: &CacheParamConfig{Limit: -1, + TTL: time.Duration(0), StaticTTL: false, Precache: false}, + utils.CacheCDRStatS: &CacheParamConfig{Limit: -1, + TTL: time.Duration(0), StaticTTL: false, Precache: false}, + utils.CacheActions: &CacheParamConfig{Limit: -1, + TTL: time.Duration(0), StaticTTL: false, Precache: false}, + utils.CacheActionPlans: &CacheParamConfig{Limit: -1, + TTL: time.Duration(0), StaticTTL: false, Precache: false}, + utils.CacheAccountActionPlans: &CacheParamConfig{Limit: -1, + TTL: time.Duration(0), StaticTTL: false, Precache: false}, + utils.CacheActionTriggers: &CacheParamConfig{Limit: -1, + TTL: time.Duration(0), StaticTTL: false, Precache: false}, + utils.CacheSharedGroups: &CacheParamConfig{Limit: -1, + TTL: time.Duration(0), StaticTTL: false, Precache: false}, + utils.CacheAliases: &CacheParamConfig{Limit: -1, + TTL: time.Duration(0), StaticTTL: false, Precache: false}, + utils.CacheReverseAliases: &CacheParamConfig{Limit: -1, + TTL: time.Duration(0), StaticTTL: false, Precache: false}, + utils.CacheDerivedChargers: &CacheParamConfig{Limit: -1, + TTL: time.Duration(0), StaticTTL: false, Precache: false}, + utils.CacheResourceConfigs: &CacheParamConfig{Limit: -1, + TTL: time.Duration(0), StaticTTL: false, Precache: false}, + utils.CacheTimings: &CacheParamConfig{Limit: -1, + TTL: time.Duration(0), StaticTTL: false, Precache: false}, } if !reflect.DeepEqual(eCacheCfg, cgrCfg.CacheConfig) { - t.Errorf("received: %+v, expecting: %+v", eCacheCfg, cgrCfg.CacheConfig) + t.Errorf("received: %s, \nexpecting: %s", utils.ToIJSON(eCacheCfg), utils.ToIJSON(cgrCfg.CacheConfig)) } } diff --git a/engine/history_test.go b/engine/history_test.go index 4d9b6d25c..c834ac609 100644 --- a/engine/history_test.go +++ b/engine/history_test.go @@ -35,8 +35,7 @@ func TestHistoryRatinPlans(t *testing.T) { func TestHistoryDestinations(t *testing.T) { scribe := historyScribe.(*history.MockScribe) buf := scribe.GetBuffer(history.DESTINATIONS_FN) - expected := `{"Id":"*ddc_test","Prefixes":["333","666"]}, -{"Id":"ALL","Prefixes":["49","41","43"]}, + expected := `{"Id":"ALL","Prefixes":["49","41","43"]}, {"Id":"DST_TCDDBSWF","Prefixes":["1716"]}, {"Id":"DST_UK_Mobile_BIG5","Prefixes":["447956"]}, {"Id":"EU_LANDLINE","Prefixes":["444"]}, diff --git a/engine/lcr.go b/engine/lcr.go index 375b87d13..769721785 100644 --- a/engine/lcr.go +++ b/engine/lcr.go @@ -197,22 +197,22 @@ func (le *LCREntry) GetQOSLimits() (minASR, maxASR float64, minPDD, maxPDD, minA if maxASR, err = strconv.ParseFloat(params[1], 64); err != nil { maxASR = -1 } - if minPDD, err = utils.ParseDurationWithSecs(params[2]); err != nil { + if minPDD, err = utils.ParseDurationWithSecs(params[2]); err != nil || params[2] == "" { minPDD = -1 } - if maxPDD, err = utils.ParseDurationWithSecs(params[3]); err != nil { + if maxPDD, err = utils.ParseDurationWithSecs(params[3]); err != nil || params[3] == "" { maxPDD = -1 } - if minACD, err = utils.ParseDurationWithSecs(params[4]); err != nil { + if minACD, err = utils.ParseDurationWithSecs(params[4]); err != nil || params[4] == "" { minACD = -1 } - if maxACD, err = utils.ParseDurationWithSecs(params[5]); err != nil { + if maxACD, err = utils.ParseDurationWithSecs(params[5]); err != nil || params[5] == "" { maxACD = -1 } - if minTCD, err = utils.ParseDurationWithSecs(params[6]); err != nil { + if minTCD, err = utils.ParseDurationWithSecs(params[6]); err != nil || params[6] == "" { minTCD = -1 } - if maxTCD, err = utils.ParseDurationWithSecs(params[7]); err != nil { + if maxTCD, err = utils.ParseDurationWithSecs(params[7]); err != nil || params[7] == "" { maxTCD = -1 } if minACC, err = strconv.ParseFloat(params[8], 64); err != nil { diff --git a/engine/lcr_test.go b/engine/lcr_test.go index 607af57c1..b28f99752 100644 --- a/engine/lcr_test.go +++ b/engine/lcr_test.go @@ -119,7 +119,8 @@ func TestLcrGetQosLimitsSome(t *testing.T) { minAcc != 1 || maxAcc != -1 || minTcc != 3 || maxTcc != -1 || minDdc != -1 || maxDdc != 2 { - t.Error("Wrong qos limits parsed: ", minAsr, maxAsr, minAcd, maxAcd, minTcd, maxTcd, minTcc, maxTcc, minDdc, maxDdc) + t.Errorf("Wrong qos limits parsed: <%v>, <%v>, <%v>, <%v>, <%v>, <%v>, <%v>, <%v>, <%v>, <%v>", + minAsr, maxAsr, minAcd, maxAcd, minTcd, maxTcd, minTcc, maxTcc, minDdc, maxDdc) } } diff --git a/engine/resources.go b/engine/resources.go index 5a9f86e80..8815bf772 100755 --- a/engine/resources.go +++ b/engine/resources.go @@ -29,6 +29,7 @@ import ( "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/guardian" "github.com/cgrates/cgrates/utils" + "github.com/cgrates/ltcache" "github.com/cgrates/rpcclient" ) @@ -223,20 +224,22 @@ func NewResourceService(cfg *config.CGRConfig, dataDB DataDB, statS rpcclient.Rp if statS != nil && reflect.ValueOf(statS).IsNil() { statS = nil } - return &ResourceService{dataDB: dataDB, statS: statS}, nil + return &ResourceService{dataDB: dataDB, statS: statS, + scEventResources: ltcache.New(ltcache.UnlimitedCaching, time.Duration(1)*time.Minute, false, nil), + lcEventResources: ltcache.New(ltcache.UnlimitedCaching, ltcache.UnlimitedCaching, false, nil)}, nil } // ResourceService is the service handling resources type ResourceService struct { - cfg *config.CGRConfig - dataDB DataDB // So we can load the data in cache and index it - statS rpcclient.RpcClientConnection - eventResources map[string][]string // map[ruID][]string{rID} for faster queries - erMux sync.RWMutex - storedResources utils.StringMap // keep a record of resources which need saving, map[resID]bool - srMux sync.RWMutex - stopBackup chan struct{} // control storing process - backupInterval time.Duration + cfg *config.CGRConfig + dataDB DataDB // So we can load the data in cache and index it + statS rpcclient.RpcClientConnection // allows applying filters based on stats + scEventResources *ltcache.Cache // short cache map[ruID], used to keep references to matched resources for events in allow queries + lcEventResources *ltcache.Cache // cache recording resources for events in alocation phase + storedResources utils.StringMap // keep a record of resources which need saving, map[resID]bool + srMux sync.RWMutex + stopBackup chan struct{} // control storing process + backupInterval time.Duration } // Called to start the service @@ -318,25 +321,39 @@ func (rS *ResourceService) runBackup() { // cachedResourcesForEvent attempts to retrieve cached resources for an event // returns nil if event not cached or errors occur +// returns []Resource if negative reply was cached func (rS *ResourceService) cachedResourcesForEvent(evUUID string) (rs Resources) { - rS.erMux.RLock() - rIDs, has := rS.eventResources[evUUID] - rS.erMux.RUnlock() + var shortCached bool + rIDsIf, has := rS.lcEventResources.Get(evUUID) if !has { - return nil + if rIDsIf, has = rS.scEventResources.Get(evUUID); !has { + return nil + } + shortCached = true } + var rIDs []string + if rIDsIf != nil { + rIDs = rIDsIf.([]string) + } + rs = make(Resources, len(rIDs)) + if len(rIDs) == 0 { + return + } + lockIDs := utils.PrefixSliceItems(rIDs, utils.ResourcesPrefix) guardian.Guardian.GuardIDs(rS.cfg.LockingTimeout, lockIDs...) defer guardian.Guardian.UnguardIDs(lockIDs...) - rs = make(Resources, len(rIDs)) for i, rID := range rIDs { if r, err := rS.dataDB.GetResource(rID, false, ""); err != nil { utils.Logger.Warning( fmt.Sprintf(" force-uncaching resources for evUUID: <%s>, error: <%s>", evUUID, err.Error())) - rS.erMux.Lock() - delete(rS.eventResources, evUUID) - rS.erMux.Unlock() + // on errors, cleanup cache so we recache + if shortCached { + rS.scEventResources.Remove(evUUID) + } else { + rS.lcEventResources.Remove(evUUID) + } return nil } else { rs[i] = r @@ -410,7 +427,7 @@ func (rS *ResourceService) matchingResourcesForEvent(ev map[string]interface{}) func (rS *ResourceService) V1ResourcesForEvent(ev map[string]interface{}, reply *[]*ResourceCfg) error { matchingRLForEv, err := rS.matchingResourcesForEvent(ev) if err != nil { - return utils.NewErrServerError(err) + return err } if len(matchingRLForEv) == 0 { return utils.ErrNotFound @@ -428,11 +445,13 @@ func (rS *ResourceService) V1AllowUsage(args utils.AttrRLsResourceUsage, allow * if mtcRLs, err = rS.matchingResourcesForEvent(args.Event); err != nil { return err } + rS.scEventResources.Set(args.UsageID, mtcRLs.ids()) } if _, err = mtcRLs.AllocateResource( &ResourceUsage{ID: args.UsageID, Units: args.Units}, true); err != nil { if err == utils.ErrResourceUnavailable { + rS.scEventResources.Set(args.UsageID, nil) return // not error but still not allowed } return err @@ -443,20 +462,33 @@ func (rS *ResourceService) V1AllowUsage(args utils.AttrRLsResourceUsage, allow * // V1AllocateResource is called when a resource requires allocation func (rS *ResourceService) V1AllocateResource(args utils.AttrRLsResourceUsage, reply *string) (err error) { + var wasCached bool mtcRLs := rS.cachedResourcesForEvent(args.UsageID) if mtcRLs == nil { if mtcRLs, err = rS.matchingResourcesForEvent(args.Event); err != nil { return } + } else { + wasCached = true } alcMsg, err := mtcRLs.AllocateResource(&ResourceUsage{ID: args.UsageID, Units: args.Units}, false) if err != nil { return err } + // index it for matching out of cache - rS.erMux.Lock() - rS.eventResources[args.UsageID] = mtcRLs.ids() - rS.erMux.Unlock() + var wasShortCached bool + if wasCached { + if _, has := rS.scEventResources.Get(args.UsageID); has { + // remove from short cache to populate event cache + wasShortCached = true + rS.scEventResources.Remove(args.UsageID) + } + } + if wasShortCached || !wasCached { + rS.lcEventResources.Set(args.UsageID, mtcRLs.ids()) + } + // index it for storing rS.srMux.Lock() for _, r := range mtcRLs { @@ -481,9 +513,7 @@ func (rS *ResourceService) V1ReleaseResource(args utils.AttrRLsResourceUsage, re } } mtcRLs.clearUsage(args.UsageID) - rS.erMux.Lock() - delete(rS.eventResources, args.UsageID) - rS.erMux.Unlock() + rS.lcEventResources.Remove(args.UsageID) if rS.backupInterval != -1 { rS.srMux.Lock() } diff --git a/engine/storage_map.go b/engine/storage_map.go index 1adafa2af..9c6413ced 100755 --- a/engine/storage_map.go +++ b/engine/storage_map.go @@ -71,7 +71,8 @@ func (s storage) smembers(key string, ms Marshaler) (idMap utils.StringMap, ok b } func NewMapStorage() (*MapStorage, error) { - return &MapStorage{dict: make(map[string][]byte), ms: NewCodecMsgpackMarshaler(), cacheCfg: config.CgrConfig().CacheConfig}, nil + return &MapStorage{dict: make(map[string][]byte), ms: NewCodecMsgpackMarshaler(), + cacheCfg: config.CgrConfig().CacheConfig}, nil } func NewMapStorageJson() (mpStorage *MapStorage, err error) { @@ -247,7 +248,7 @@ func (ms *MapStorage) CacheDataFromDB(prefix string, IDs []string, mustBeCached if cCfg, has := ms.cacheCfg[utils.CachePrefixToInstance[prefix]]; has { nrItems = cCfg.Limit } - if nrItems != 0 && nrItems < len(IDs) { + if nrItems > 0 && nrItems < len(IDs) { IDs = IDs[:nrItems] } } diff --git a/glide.lock b/glide.lock index edd14a20a..d933b383c 100644 --- a/glide.lock +++ b/glide.lock @@ -16,7 +16,7 @@ imports: - name: github.com/cgrates/kamevapi version: a376b1f937ba959857929fa3e111c0f3243278c0 - name: github.com/cgrates/ltcache - version: c4fd16ee97ba74e5a0623ff4717fc964478acf65 + version: 94ec8a132c7e1c46c409eb5d358f3226ae8a9abf - name: github.com/cgrates/osipsdagram version: 3d6beed663452471dec3ca194137a30d379d9e8f - name: github.com/cgrates/radigo diff --git a/utils/coreutils.go b/utils/coreutils.go index 90175336a..d510abe0a 100644 --- a/utils/coreutils.go +++ b/utils/coreutils.go @@ -265,8 +265,11 @@ func CopyHour(src, dest time.Time) time.Time { } // Parses duration, considers s as time unit if not provided, seconds as float to specify subunits -func ParseDurationWithSecs(durStr string) (time.Duration, error) { - if _, err := strconv.ParseFloat(durStr, 64); err == nil { // Seconds format considered +func ParseDurationWithSecs(durStr string) (d time.Duration, err error) { + if durStr == "" { + return + } + if _, err = strconv.ParseFloat(durStr, 64); err == nil { // Seconds format considered durStr += "s" } return time.ParseDuration(durStr)