diff --git a/apier/v1/apier.go b/apier/v1/apier.go index 0f851ffcf..f2e48893c 100644 --- a/apier/v1/apier.go +++ b/apier/v1/apier.go @@ -1015,6 +1015,19 @@ func (self *ApierV1) ReloadCache(attrs utils.AttrReloadCache, reply *string) (er if err = self.DataManager.CacheDataFromDB(utils.AttributeProfilePrefix, dataIDs, true); err != nil { return } + // ChargerProfiles + dataIDs = make([]string, 0) + if attrs.ChargerProfileIDs == nil { + dataIDs = nil // Reload all + } else if len(*attrs.ChargerProfileIDs) > 0 { + dataIDs = make([]string, len(*attrs.ChargerProfileIDs)) + for idx, dId := range *attrs.ChargerProfileIDs { + dataIDs[idx] = dId + } + } + if err = self.DataManager.CacheDataFromDB(utils.ChargerProfilePrefix, dataIDs, true); err != nil { + return + } *reply = utils.OK return nil @@ -1024,7 +1037,7 @@ func (self *ApierV1) LoadCache(args utils.AttrReloadCache, reply *string) (err e if args.FlushAll { engine.Cache.Clear(nil) } - var dstIDs, rvDstIDs, rplIDs, rpfIDs, actIDs, aplIDs, aapIDs, atrgIDs, sgIDs, lcrIDs, dcIDs, alsIDs, rvAlsIDs, rspIDs, resIDs, stqIDs, stqpIDs, thIDs, thpIDs, fltrIDs, splpIDs, alsPrfIDs []string + var dstIDs, rvDstIDs, rplIDs, rpfIDs, actIDs, aplIDs, aapIDs, atrgIDs, sgIDs, lcrIDs, dcIDs, alsIDs, rvAlsIDs, rspIDs, resIDs, stqIDs, stqpIDs, thIDs, thpIDs, fltrIDs, splpIDs, alsPrfIDs, cppIDs []string if args.DestinationIDs == nil { dstIDs = nil } else { @@ -1135,7 +1148,15 @@ func (self *ApierV1) LoadCache(args utils.AttrReloadCache, reply *string) (err e } else { alsPrfIDs = *args.AttributeProfileIDs } - if err := self.DataManager.LoadDataDBCache(dstIDs, rvDstIDs, rplIDs, rpfIDs, actIDs, aplIDs, aapIDs, atrgIDs, sgIDs, lcrIDs, dcIDs, alsIDs, rvAlsIDs, rspIDs, resIDs, stqIDs, stqpIDs, thIDs, thpIDs, fltrIDs, splpIDs, alsPrfIDs); err != nil { + if args.ChargerProfileIDs == nil { + cppIDs = nil + } else { + cppIDs = *args.ChargerProfileIDs + } + if err := self.DataManager.LoadDataDBCache(dstIDs, rvDstIDs, rplIDs, + rpfIDs, actIDs, aplIDs, aapIDs, atrgIDs, sgIDs, lcrIDs, dcIDs, alsIDs, + rvAlsIDs, rspIDs, resIDs, stqIDs, stqpIDs, thIDs, thpIDs, + fltrIDs, splpIDs, alsPrfIDs, cppIDs); err != nil { return utils.NewErrServerError(err) } *reply = utils.OK @@ -1316,6 +1337,14 @@ func (self *ApierV1) FlushCache(args utils.AttrReloadCache, reply *string) (err true, utils.NonTransactional) } } + if args.ChargerProfileIDs == nil { + engine.Cache.Clear([]string{utils.CacheChargerProfiles}) + } else if len(*args.ChargerProfileIDs) != 0 { + for _, key := range *args.ChargerProfileIDs { + engine.Cache.Remove(utils.CacheChargerProfiles, key, + true, utils.NonTransactional) + } + } *reply = utils.OK return @@ -1344,6 +1373,7 @@ func (self *ApierV1) GetCacheStats(attrs utils.AttrCacheStats, reply *utils.Cach cs.Filters = len(engine.Cache.GetItemIDs(utils.CacheFilters, "")) cs.SupplierProfiles = len(engine.Cache.GetItemIDs(utils.CacheSupplierProfiles, "")) cs.AttributeProfiles = len(engine.Cache.GetItemIDs(utils.CacheAttributeProfiles, "")) + cs.ChargerProfiles = len(engine.Cache.GetItemIDs(utils.CacheChargerProfiles, "")) if self.CdrStatsSrv != nil { var queueIds []string @@ -1772,6 +1802,25 @@ func (v1 *ApierV1) GetCacheKeys(args utils.ArgsCacheKeys, reply *utils.ArgsCache } } + if args.ChargerProfileIDs != nil { + var ids []string + if len(*args.ChargerProfileIDs) != 0 { + for _, id := range *args.ChargerProfileIDs { + if _, hasIt := engine.Cache.Get(utils.CacheChargerProfiles, id); hasIt { + ids = append(ids, id) + } + } + } else { + for _, id := range engine.Cache.GetItemIDs(utils.CacheChargerProfiles, "") { + ids = append(ids, id) + } + } + ids = args.Paginator.PaginateStringSlice(ids) + if len(ids) != 0 { + reply.ChargerProfileIDs = &ids + } + } + return } diff --git a/apier/v1/chargers.go b/apier/v1/chargers.go index 02f66f697..b948f1a95 100644 --- a/apier/v1/chargers.go +++ b/apier/v1/chargers.go @@ -23,6 +23,50 @@ import ( "github.com/cgrates/cgrates/utils" ) +// GetChargerProfile returns a Charger Profile +func (apierV1 *ApierV1) GetChargerProfile(arg utils.TenantID, reply *engine.ChargerProfile) error { + if missing := utils.MissingStructFields(&arg, []string{"Tenant", "ID"}); len(missing) != 0 { //Params missing + return utils.NewErrMandatoryIeMissing(missing...) + } + if cpp, err := apierV1.DataManager.GetChargerProfile(arg.Tenant, arg.ID, false, utils.NonTransactional); err != nil { + if err.Error() != utils.ErrNotFound.Error() { + err = utils.NewErrServerError(err) + } + return err + } else { + *reply = *cpp + } + return nil +} + +//SetChargerProfile add/update a new Charger Profile +func (apierV1 *ApierV1) SetChargerProfile(cpp *engine.ChargerProfile, reply *string) error { + if missing := utils.MissingStructFields(cpp, []string{"Tenant", "ID"}); len(missing) != 0 { + return utils.NewErrMandatoryIeMissing(missing...) + } + if err := apierV1.DataManager.SetChargerProfile(cpp, true); err != nil { + return utils.APIErrorHandler(err) + } + *reply = utils.OK + return nil +} + +//RemoveChargerProfile remove a specific Charger Profile +func (apierV1 *ApierV1) RemoveChargerProfile(arg utils.TenantID, reply *string) error { + if missing := utils.MissingStructFields(&arg, []string{"Tenant", "ID"}); len(missing) != 0 { //Params missing + return utils.NewErrMandatoryIeMissing(missing...) + } + if err := apierV1.DataManager.RemoveChargerProfile(arg.Tenant, + arg.ID, utils.NonTransactional, true); err != nil { + if err.Error() != utils.ErrNotFound.Error() { + err = utils.NewErrServerError(err) + } + return err + } + *reply = utils.OK + return nil +} + func NewChargerSv1(cS *engine.ChargerService) *ChargerSv1 { return &ChargerSv1{cS: cS} } diff --git a/cmd/cgr-tester/cgr-tester.go b/cmd/cgr-tester/cgr-tester.go index befec7b98..d47a434b7 100644 --- a/cmd/cgr-tester/cgr-tester.go +++ b/cmd/cgr-tester/cgr-tester.go @@ -77,7 +77,7 @@ func durInternalRater(cd *engine.CallDescriptor) (time.Duration, error) { } defer dm.DataDB().Close() engine.SetDataStorage(dm) - if err := dm.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil); err != nil { + if err := dm.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil); err != nil { return nilDuration, fmt.Errorf("Cache rating error: %s", err.Error()) } log.Printf("Runnning %d cycles...", *runs) diff --git a/engine/datamanager.go b/engine/datamanager.go index 69622ec3e..aedf27d07 100644 --- a/engine/datamanager.go +++ b/engine/datamanager.go @@ -46,7 +46,7 @@ func (dm *DataManager) DataDB() DataDB { func (dm *DataManager) LoadDataDBCache(dstIDs, rvDstIDs, rplIDs, rpfIDs, actIDs, aplIDs, aaPlIDs, atrgIDs, sgIDs, lcrIDs, dcIDs, alsIDs, rvAlsIDs, rpIDs, resIDs, - stqIDs, stqpIDs, thIDs, thpIDs, fltrIDs, splPrflIDs, alsPrfIDs []string) (err error) { + stqIDs, stqpIDs, thIDs, thpIDs, fltrIDs, splPrflIDs, alsPrfIDs, cppIDs []string) (err error) { if dm.DataDB().GetStorageType() == utils.MAPSTOR { if dm.cacheCfg == nil { return @@ -58,7 +58,7 @@ func (dm *DataManager) LoadDataDBCache(dstIDs, rvDstIDs, rplIDs, rpfIDs, actIDs, utils.ACTION_PREFIX, utils.ACTION_PLAN_PREFIX, utils.ACTION_TRIGGER_PREFIX, utils.SHARED_GROUP_PREFIX, utils.ALIASES_PREFIX, utils.REVERSE_ALIASES_PREFIX, utils.StatQueuePrefix, utils.StatQueueProfilePrefix, utils.ThresholdPrefix, utils.ThresholdProfilePrefix, - utils.FilterPrefix, utils.SupplierProfilePrefix, utils.AttributeProfilePrefix}, k) && cacheCfg.Precache { + utils.FilterPrefix, utils.SupplierProfilePrefix, utils.AttributeProfilePrefix, utils.ChargerProfilePrefix}, k) && cacheCfg.Precache { if err := dm.PreloadCacheForPrefix(k); err != nil && err != utils.ErrInvalidKey { return err } @@ -89,6 +89,7 @@ func (dm *DataManager) LoadDataDBCache(dstIDs, rvDstIDs, rplIDs, rpfIDs, actIDs, utils.FilterPrefix: fltrIDs, utils.SupplierProfilePrefix: splPrflIDs, utils.AttributeProfilePrefix: alsPrfIDs, + utils.ChargerProfilePrefix: cppIDs, } { if err = dm.CacheDataFromDB(key, ids, false); err != nil { return @@ -148,7 +149,8 @@ func (dm *DataManager) CacheDataFromDB(prfx string, ids []string, mustBeCached b utils.ThresholdProfilePrefix, utils.FilterPrefix, utils.SupplierProfilePrefix, - utils.AttributeProfilePrefix}, prfx) { + utils.AttributeProfilePrefix, + utils.ChargerProfilePrefix}, prfx) { return utils.NewCGRError(utils.DataManager, utils.MandatoryIEMissingCaps, utils.UnsupportedCachePrefix, @@ -240,6 +242,9 @@ func (dm *DataManager) CacheDataFromDB(prfx string, ids []string, mustBeCached b case utils.AttributeProfilePrefix: tntID := utils.NewTenantID(dataID) _, err = dm.GetAttributeProfile(tntID.Tenant, tntID.ID, true, utils.NonTransactional) + case utils.ChargerProfilePrefix: + tntID := utils.NewTenantID(dataID) + _, err = dm.GetChargerProfile(tntID.Tenant, tntID.ID, true, utils.NonTransactional) } if err != nil { return utils.NewCGRError(utils.DataManager, @@ -1159,14 +1164,50 @@ func (dm *DataManager) RemoveAttributeProfile(tenant, id string, contexts []stri func (dm *DataManager) GetChargerProfile(tenant, id string, skipCache bool, transactionID string) (cpp *ChargerProfile, err error) { + tntID := utils.ConcatenatedKey(tenant, id) + if !skipCache { + if x, ok := Cache.Get(utils.CacheChargerProfiles, tntID); ok { + if x == nil { + return nil, utils.ErrNotFound + } + return x.(*ChargerProfile), nil + } + } + cpp, err = dm.dataDB.GetChargerProfileDrv(tenant, id) + if err != nil { + if err == utils.ErrNotFound { + Cache.Set(utils.CacheChargerProfiles, tntID, nil, nil, + cacheCommit(transactionID), transactionID) + } + return nil, err + } + Cache.Set(utils.CacheChargerProfiles, tntID, cpp, nil, + cacheCommit(transactionID), transactionID) return } func (dm *DataManager) SetChargerProfile(cpp *ChargerProfile, withIndex bool) (err error) { + if err = dm.DataDB().SetChargerProfileDrv(cpp); err != nil { + return err + } + if err = dm.CacheDataFromDB(utils.ChargerProfilePrefix, []string{cpp.TenantID()}, true); err != nil { + return + } + if withIndex { + return createAndIndex(utils.ChargerProfilePrefix, cpp.Tenant, utils.EmptyString, cpp.ID, cpp.FilterIDs, dm) + } return } func (dm *DataManager) RemoveChargerProfile(tenant, id string, transactionID string, withIndex bool) (err error) { + if err = dm.DataDB().RemoveChargerProfileDrv(tenant, id); err != nil { + return + } + Cache.Remove(utils.CacheChargerProfiles, utils.ConcatenatedKey(tenant, id), + cacheCommit(transactionID), transactionID) + if withIndex { + return NewFilterIndexer(dm, utils.ChargerProfilePrefix, tenant).RemoveItemFromIndex(id) + } return } diff --git a/engine/storage_mongo_datadb.go b/engine/storage_mongo_datadb.go index f5651fcf3..1d005d410 100644 --- a/engine/storage_mongo_datadb.go +++ b/engine/storage_mongo_datadb.go @@ -664,6 +664,11 @@ func (ms *MongoStorage) GetKeysForPrefix(prefix string) (result []string, err er for iter.Next(&idResult) { result = append(result, utils.AttributeProfilePrefix+utils.ConcatenatedKey(idResult.Tenant, idResult.Id)) } + case utils.ChargerProfilePrefix: + iter := db.C(colCpp).Find(bson.M{"id": bson.M{"$regex": bson.RegEx{Pattern: subject}}}).Select(bson.M{"tenant": 1, "id": 1}).Iter() + for iter.Next(&idResult) { + result = append(result, utils.ChargerProfilePrefix+utils.ConcatenatedKey(idResult.Tenant, idResult.Id)) + } default: err = fmt.Errorf("unsupported prefix in GetKeysForPrefix: %s", prefix) } @@ -718,6 +723,9 @@ func (ms *MongoStorage) HasDataDrv(category, subject, tenant string) (has bool, case utils.AttributeProfilePrefix: count, err = db.C(colAttr).Find(bson.M{"tenant": tenant, "id": subject}).Count() has = count > 0 + case utils.ChargerProfilePrefix: + count, err = db.C(colCpp).Find(bson.M{"tenant": tenant, "id": subject}).Count() + has = count > 0 default: err = fmt.Errorf("unsupported category in HasData: %s", category) } diff --git a/general_tests/acntacts_test.go b/general_tests/acntacts_test.go index 353daf966..3d6f5f2d9 100644 --- a/general_tests/acntacts_test.go +++ b/general_tests/acntacts_test.go @@ -69,7 +69,7 @@ ENABLE_ACNT,*enable_account,,,,,,,,,,,,,,false,false,10` csvr.WriteToDatabase(false, false, false) engine.Cache.Clear(nil) - dbAcntActs.LoadDataDBCache(nil, nil, nil, nil, + dbAcntActs.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil) diff --git a/general_tests/auth_test.go b/general_tests/auth_test.go index 9cca5de88..b8ec8f994 100644 --- a/general_tests/auth_test.go +++ b/general_tests/auth_test.go @@ -80,7 +80,7 @@ RP_ANY,DR_ANY_1CNT,*any,10` } engine.Cache.Clear(nil) - dbAuth.LoadDataDBCache(nil, nil, nil, nil, nil, + dbAuth.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil) diff --git a/general_tests/costs1_test.go b/general_tests/costs1_test.go index ac21b7193..796eaa056 100644 --- a/general_tests/costs1_test.go +++ b/general_tests/costs1_test.go @@ -73,7 +73,7 @@ RP_SMS1,DR_SMS_1,ALWAYS,10` } csvr.WriteToDatabase(false, false, false) engine.Cache.Clear(nil) - dataDB.LoadDataDBCache(nil, nil, nil, nil, nil, nil, + dataDB.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil) diff --git a/general_tests/datachrg1_test.go b/general_tests/datachrg1_test.go index fd110de9f..bc243aa81 100644 --- a/general_tests/datachrg1_test.go +++ b/general_tests/datachrg1_test.go @@ -60,7 +60,7 @@ RP_DATA1,DR_DATA_2,TM2,10` } csvr.WriteToDatabase(false, false, false) engine.Cache.Clear(nil) - dataDB.LoadDataDBCache(nil, nil, nil, nil, + dataDB.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil) diff --git a/general_tests/ddazmbl1_test.go b/general_tests/ddazmbl1_test.go index f20a92025..ada7a6223 100644 --- a/general_tests/ddazmbl1_test.go +++ b/general_tests/ddazmbl1_test.go @@ -119,7 +119,7 @@ TOPUP10_AT,TOPUP10_AC1,ASAP,10` } engine.Cache.Clear(nil) - dataDB.LoadDataDBCache(nil, nil, nil, nil, + dataDB.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil) diff --git a/general_tests/ddazmbl2_test.go b/general_tests/ddazmbl2_test.go index dcc897e3a..2f6374e6d 100644 --- a/general_tests/ddazmbl2_test.go +++ b/general_tests/ddazmbl2_test.go @@ -116,7 +116,7 @@ TOPUP10_AT,TOPUP10_AC1,ASAP,10` t.Error("No account saved") } engine.Cache.Clear(nil) - dataDB2.LoadDataDBCache(nil, nil, nil, nil, nil, + dataDB2.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil) diff --git a/general_tests/ddazmbl3_test.go b/general_tests/ddazmbl3_test.go index 1ecfdc93e..e746b603b 100644 --- a/general_tests/ddazmbl3_test.go +++ b/general_tests/ddazmbl3_test.go @@ -114,7 +114,7 @@ RP_UK,DR_UK_Mobile_BIG5,ALWAYS,10` t.Error("No account saved") } engine.Cache.Clear(nil) - dataDB3.LoadDataDBCache(nil, nil, nil, nil, + dataDB3.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil) diff --git a/general_tests/smschrg1_test.go b/general_tests/smschrg1_test.go index 7090cc134..08dd2b0a7 100644 --- a/general_tests/smschrg1_test.go +++ b/general_tests/smschrg1_test.go @@ -58,7 +58,9 @@ func TestSMSLoadCsvTpSmsChrg1(t *testing.T) { } csvr.WriteToDatabase(false, false, false) engine.Cache.Clear(nil) - dataDB.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil) + dataDB.LoadDataDBCache(nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil) if cachedRPlans := len(engine.Cache.GetItemIDs(utils.CacheRatingPlans, "")); cachedRPlans != 1 { t.Error("Wrong number of cached rating plans found", cachedRPlans) diff --git a/utils/apitpdata.go b/utils/apitpdata.go index 0371622b5..371496065 100755 --- a/utils/apitpdata.go +++ b/utils/apitpdata.go @@ -677,6 +677,7 @@ type ArgsCache struct { FilterIDs *[]string SupplierProfileIDs *[]string AttributeProfileIDs *[]string + ChargerProfileIDs *[]string } // Data used to do remote cache reloads via api @@ -720,6 +721,7 @@ type CacheStats struct { Filters int SupplierProfiles int AttributeProfiles int + ChargerProfiles int } type AttrExpFileCdrs struct {