From 25a1858eacb5d25b337e9a2e4d3d4540c2fec5b5 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Mon, 6 Apr 2015 18:30:40 +0300 Subject: [PATCH] fixes and tests for lcr --- .../mysql/create_tariffplan_tables.sql | 6 +-- .../postgres/create_tariffplan_tables.sql | 6 +-- engine/calldesc.go | 39 +++++++++++++------ engine/lcr.go | 10 +++-- engine/lcr_test.go | 17 ++++++++ engine/loader_csv.go | 2 +- engine/ratingprofile.go | 1 + engine/storage_sql.go | 8 ++-- utils/coreutils.go | 4 ++ 9 files changed, 67 insertions(+), 26 deletions(-) diff --git a/data/storage/mysql/create_tariffplan_tables.sql b/data/storage/mysql/create_tariffplan_tables.sql index 8d0ab8a8d..0518a0be9 100644 --- a/data/storage/mysql/create_tariffplan_tables.sql +++ b/data/storage/mysql/create_tariffplan_tables.sql @@ -246,10 +246,10 @@ CREATE TABLE `tp_account_actions` ( DROP TABLE IF EXISTS tp_lcr_rules; CREATE TABLE tp_lcr_rules ( `id` int(11) NOT NULL AUTO_INCREMENT, - `tpid` varchar(64) NOT NULL, - `tenant` varchar(64) NOT NULL, - `category` varchar(32) NOT NULL, + `tpid` varchar(64) NOT NULL, `direction` varchar(8) NOT NULL, + `tenant` varchar(64) NOT NULL, + `category` varchar(32) NOT NULL, `account` varchar(24) NOT NULL, `subject` varchar(64) NOT NULL, `destination_tag` varchar(64) NOT NULL, diff --git a/data/storage/postgres/create_tariffplan_tables.sql b/data/storage/postgres/create_tariffplan_tables.sql index 4c19e6ed8..766671bd2 100644 --- a/data/storage/postgres/create_tariffplan_tables.sql +++ b/data/storage/postgres/create_tariffplan_tables.sql @@ -241,10 +241,10 @@ CREATE INDEX tpaccountactions_idx ON tp_account_actions (tpid,loadid,tenant,acco DROP TABLE IF EXISTS tp_lcr_rules; CREATE TABLE tp_lcr_rules ( id SERIAL PRIMARY KEY, - tpid VARCHAR(64) NOT NULL, - tenant VARCHAR(64) NOT NULL, - category VARCHAR(32) NOT NULL, + tpid VARCHAR(64) NOT NULL, direction VARCHAR(8) NOT NULL, + tenant VARCHAR(64) NOT NULL, + category VARCHAR(32) NOT NULL, account VARCHAR(24) NOT NULL, subject VARCHAR(64) NOT NULL, destination_tag VARCHAR(64) NOT NULL, diff --git a/engine/calldesc.go b/engine/calldesc.go index 64c019bd6..b5ddfc686 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -292,10 +292,6 @@ func (cd *CallDescriptor) GetAccountKey() string { return utils.ConcatenatedKey(cd.Direction, cd.Tenant, subj) } -func (cd *CallDescriptor) GetLCRKey(subj string) string { - return utils.ConcatenatedKey(cd.Direction, cd.Tenant, cd.Category, cd.Account, cd.Subject) -} - // Splits the received timespan into sub time spans according to the activation periods intervals. func (cd *CallDescriptor) splitInTimeSpans() (timespans []*TimeSpan) { firstSpan := &TimeSpan{TimeStart: cd.TimeStart, TimeEnd: cd.TimeEnd, DurationIndex: cd.DurationIndex} @@ -657,19 +653,35 @@ func (cd *CallDescriptor) Clone() *CallDescriptor { } } -func (cd *CallDescriptor) GetLCR(stats StatsInterface) (LCRCost, error) { - lcr, err := dataStorage.GetLCR(cd.GetLCRKey(""), false) - if err != nil || lcr == nil { - // try the *any customer - if lcr, err = dataStorage.GetLCR(cd.GetLCRKey(utils.ANY), false); err != nil || lcr == nil { +func (cd *CallDescriptor) GetLCRFromStorage() (*LCR, error) { + keyVariants := []string{ + utils.LCRKey(cd.Direction, cd.Tenant, cd.Category, cd.Account, cd.Subject), + utils.LCRKey(cd.Direction, cd.Tenant, cd.Category, cd.Account, utils.ANY), + utils.LCRKey(cd.Direction, cd.Tenant, cd.Category, utils.ANY, utils.ANY), + utils.LCRKey(cd.Direction, cd.Tenant, utils.ANY, utils.ANY, utils.ANY), + utils.LCRKey(cd.Direction, utils.ANY, utils.ANY, utils.ANY, utils.ANY), + } + for _, key := range keyVariants { + if lcr, err := dataStorage.GetLCR(key, false); err != nil && err.Error() != utils.ERR_NOT_FOUND { return nil, err + } else if err == nil { + return lcr, nil } } + return nil, errors.New(utils.ERR_NOT_FOUND) +} + +func (cd *CallDescriptor) GetLCR(stats StatsInterface) (LCRCost, error) { + lcr, err := cd.GetLCRFromStorage() + if err != nil { + return nil, err + } lcr.Sort() lcrCost := LCRCost{&LCRTimeSpan{StartTime: cd.TimeStart}} for _, lcrActivation := range lcr.Activations { - // TODO: filer entry by destination + //log.Printf("Activation: %+v", lcrActivation) lcrEntry := lcrActivation.GetLCREntryForPrefix(cd.Destination) + //log.Printf("Entry: %+v", lcrEntry) if lcrActivation.ActivationTime.Before(cd.TimeStart) || lcrActivation.ActivationTime.Equal(cd.TimeStart) { lcrCost[0].Entry = lcrEntry @@ -684,6 +696,11 @@ func (cd *CallDescriptor) GetLCR(stats StatsInterface) (LCRCost, error) { } } for _, ts := range lcrCost { + //log.Printf("TS: %+v", ts) + if ts.Entry == nil { + continue + } + //log.Printf("Entry: %+v", ts.Entry) if ts.Entry.Strategy == LCR_STRATEGY_STATIC { for _, supplier := range ts.Entry.GetParams() { lcrCD := cd.Clone() @@ -707,7 +724,7 @@ func (cd *CallDescriptor) GetLCR(stats StatsInterface) (LCRCost, error) { } else { // find rating profiles ratingProfileSearchKey := utils.ConcatenatedKey(lcr.Direction, lcr.Tenant, ts.Entry.RPCategory) - suppliers := cache2go.GetEntriesKeys(LCR_PREFIX + ratingProfileSearchKey) + suppliers := cache2go.GetEntriesKeys(RATING_PROFILE_PREFIX + ratingProfileSearchKey) for _, supplier := range suppliers { split := strings.Split(supplier, ":") supplier = split[len(split)-1] diff --git a/engine/lcr.go b/engine/lcr.go index e69c71cbc..7a5173f6f 100644 --- a/engine/lcr.go +++ b/engine/lcr.go @@ -37,9 +37,9 @@ const ( ) type LCR struct { + Direction string Tenant string Category string - Direction string Account string Subject string Activations []*LCRActivation @@ -74,7 +74,7 @@ type LCRSupplierCost struct { } func (lcr *LCR) GetId() string { - return utils.ConcatenatedKey(lcr.Direction, lcr.Tenant, lcr.Category, lcr.Account, lcr.Subject) + return utils.LCRKey(lcr.Direction, lcr.Tenant, lcr.Category, lcr.Account, lcr.Subject) } func (lcr *LCR) Len() int { @@ -155,8 +155,10 @@ func (lcra *LCRActivation) GetLCREntryForPrefix(destination string) *LCREntry { var potentials LCREntriesSorter for _, p := range utils.SplitPrefix(destination, MIN_PREFIX_MATCH) { if x, err := cache2go.GetCached(DESTINATION_PREFIX + p); err == nil { - destIds := x.([]string) - for _, dId := range destIds { + + destIds := x.(map[interface{}]struct{}) + for idId := range destIds { + dId := idId.(string) for _, entry := range lcra.Entries { if entry.DestinationId == dId { entry.precision = len(p) diff --git a/engine/lcr_test.go b/engine/lcr_test.go index d4f867134..95df91cec 100644 --- a/engine/lcr_test.go +++ b/engine/lcr_test.go @@ -170,3 +170,20 @@ func TestLcrGetQosSortParamsFull(t *testing.T) { t.Error("Wrong qos sort params parsed: ", sort) } } + +func TestLcrGet(t *testing.T) { + cd := &CallDescriptor{ + TimeStart: time.Date(2015, 04, 06, 17, 40, 0, 0, time.UTC), + TimeEnd: time.Date(2015, 04, 06, 17, 41, 0, 0, time.UTC), + Tenant: "cgrates.org", + Direction: "*in", + Category: "call", + Destination: "0723098765", + Account: "rif", + Subject: "rif", + } + lcrs, err := cd.GetLCR(nil) + if err != nil || len(lcrs) != 1 { + t.Errorf("Bad lcr: %+v, %v", lcrs, err) + } +} diff --git a/engine/loader_csv.go b/engine/loader_csv.go index a5a5aa376..7d1934380 100644 --- a/engine/loader_csv.go +++ b/engine/loader_csv.go @@ -610,7 +610,7 @@ func (csvr *CSVReader) LoadLCRs() (err error) { } for record, err := csvReader.Read(); err == nil; record, err = csvReader.Read() { tenant, category, direction, account, subject := record[0], record[1], record[2], record[3], record[4] - id := utils.ConcatenatedKey(direction, tenant, category, account, subject) + id := utils.LCRKey(direction, tenant, category, account, subject) lcr, found := csvr.lcrs[id] activationTime, err := utils.ParseTimeDetectLayout(record[9]) if err != nil { diff --git a/engine/ratingprofile.go b/engine/ratingprofile.go index 50bdcc8ba..6bcbc04e5 100644 --- a/engine/ratingprofile.go +++ b/engine/ratingprofile.go @@ -128,6 +128,7 @@ 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.(map[interface{}]struct{}) for idId := range destIds { dId := idId.(string) diff --git a/engine/storage_sql.go b/engine/storage_sql.go index cef3b4053..fe531c719 100644 --- a/engine/storage_sql.go +++ b/engine/storage_sql.go @@ -1500,19 +1500,19 @@ func (self *SQLStorage) GetTpLCRs(tpid, tag string) (map[string]*LCR, error) { defer rows.Close() for rows.Next() { var id int - var tpid, tenant, category, direction, account, subject, destinationId, rpCategory, strategy, strategyParams, suppliers, activationTimeString string + var tpid, direction, tenant, category, account, subject, destinationId, rpCategory, strategy, strategyParams, suppliers, activationTimeString string var weight float64 - if err := rows.Scan(&id, &tpid, &tenant, &category, &direction, &account, &subject, &destinationId, &rpCategory, &strategy, &strategyParams, &suppliers, &activationTimeString, &weight); err != nil { + if err := rows.Scan(&id, &tpid, &direction, &tenant, &category, &account, &subject, &destinationId, &rpCategory, &strategy, &strategyParams, &suppliers, &activationTimeString, &weight); err != nil { return nil, err } - tag := utils.ConcatenatedKey(direction, tenant, category, account, subject) + tag := utils.LCRKey(direction, tenant, category, account, subject) lcr, found := lcrs[tag] activationTime, _ := utils.ParseTimeDetectLayout(activationTimeString) if !found { lcr = &LCR{ + Direction: direction, Tenant: tenant, Category: category, - Direction: direction, Account: account, Subject: subject, } diff --git a/utils/coreutils.go b/utils/coreutils.go index 726414e1c..e9078c574 100644 --- a/utils/coreutils.go +++ b/utils/coreutils.go @@ -259,6 +259,10 @@ func ConcatenatedKey(keyVals ...string) string { return strings.Join(keyVals, CONCATENATED_KEY_SEP) } +func LCRKey(direction, tenant, category, account, subject string) string { + return ConcatenatedKey(direction, tenant, category, account, subject) +} + func RatingSubjectAliasKey(tenant, subject string) string { return ConcatenatedKey(tenant, subject) }