From 837f9c98cbb3ef915dbde80d8c596de2fb93fae9 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Wed, 1 Apr 2015 21:31:56 +0300 Subject: [PATCH] more work on lcr --- engine/calldesc.go | 32 ++++++++++++++++++-------------- engine/lcr.go | 39 ++++++++++++++++++++++++++++++++++++--- engine/loader_csv.go | 4 ++-- 3 files changed, 56 insertions(+), 19 deletions(-) diff --git a/engine/calldesc.go b/engine/calldesc.go index b48ceee0a..9aeb4d7f3 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -275,7 +275,7 @@ func (cd *CallDescriptor) GetKey(subject string) string { subject = realSubject cd.Subject = realSubject } - return fmt.Sprintf("%s:%s:%s:%s", cd.Direction, cd.Tenant, cd.Category, subject) + return utils.ConcatenatedKey(cd.Direction, cd.Tenant, cd.Category, subject) } // Returns the key used to retrive the user balance involved in this call @@ -288,17 +288,11 @@ func (cd *CallDescriptor) GetAccountKey() string { } subj = cd.Account } - return fmt.Sprintf("%s:%s:%s", cd.Direction, cd.Tenant, subj) + return utils.ConcatenatedKey(cd.Direction, cd.Tenant, subj) } func (cd *CallDescriptor) GetLCRKey(subj string) string { - if subj == "" { - subj = cd.Subject - if cd.Account != "" { - subj = cd.Account - } - } - return fmt.Sprintf("%s:%s:%s", cd.Direction, cd.Tenant, subj) + 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. @@ -692,11 +686,14 @@ func (cd *CallDescriptor) GetLCR() (*LCRCost, error) { } for _, ts := range lcrCost.TimeSpans { if ts.Entry.Strategy == LCR_STRATEGY_STATIC { - for _, param := range strings.Split(ts.Entry.StrategyParams, ";") { - supplier := strings.TrimSpace(param) + for _, supplier := range ts.Entry.GetSuppliers() { lcrCD := cd.Clone() lcrCD.Subject = supplier - if cc, err := lcrCD.GetCost(); err != nil || cc == nil { + if cd.account, err = accountingStorage.GetAccount(cd.GetAccountKey()); err != nil { + continue + } + + if cc, err := lcrCD.debit(cd.account, true, true); err != nil || cc == nil { ts.SupplierCosts = append(ts.SupplierCosts, &LCRSupplierCost{ Supplier: supplier, Error: err, @@ -710,14 +707,21 @@ func (cd *CallDescriptor) GetLCR() (*LCRCost, error) { } } else { // find rating profiles - ratingProfileSearchKey := fmt.Sprintf("%s:%s:%s:", lcr.Direction, lcr.Tenant, ts.Entry.RPCategory) + ratingProfileSearchKey := utils.ConcatenatedKey(lcr.Direction, lcr.Tenant, ts.Entry.RPCategory) suppliers := cache2go.GetEntriesKeys(LCR_PREFIX + ratingProfileSearchKey) for _, supplier := range suppliers { split := strings.Split(supplier, ":") supplier = split[len(split)-1] lcrCD := cd.Clone() lcrCD.Subject = supplier - if cc, err := lcrCD.GetCost(); err != nil || cc == nil { + if cd.account, err = accountingStorage.GetAccount(cd.GetAccountKey()); err != nil { + continue + } + if ts.Entry.Strategy == LCR_STRATEGY_QOS_WITH_THRESHOLD { + // get stats and filter suppliers by qos thresholds + + } + if cc, err := lcrCD.debit(cd.account, true, true); err != nil || cc == nil { ts.SupplierCosts = append(ts.SupplierCosts, &LCRSupplierCost{ Supplier: supplier, Error: err, diff --git a/engine/lcr.go b/engine/lcr.go index 04c37a397..0ea217b29 100644 --- a/engine/lcr.go +++ b/engine/lcr.go @@ -20,6 +20,8 @@ package engine import ( "sort" + "strconv" + "strings" "time" "github.com/cgrates/cgrates/cache2go" @@ -27,9 +29,11 @@ import ( ) const ( - LCR_STRATEGY_STATIC = "*static" - LCR_STRATEGY_LOWEST = "*lowest" - LCR_STRATEGY_HIGHEST = "*highest" + LCR_STRATEGY_STATIC = "*static" + LCR_STRATEGY_LOWEST = "*lowest_cost" + LCR_STRATEGY_HIGHEST = "*highest_cost" + LCR_STRATEGY_QOS_WITH_THRESHOLD = "*qos_with_threshold" + LCR_STRATEGY_QOS = "*qos" ) type LCR struct { @@ -89,6 +93,35 @@ func (lcr *LCR) Sort() { sort.Sort(lcr) } +func (le *LCREntry) GetSuppliers() []string { + suppliers := strings.Split(le.StrategyParams, ";") + for i := 0; i < len(suppliers); i++ { + suppliers[i] = strings.TrimSpace(suppliers[i]) + } + return suppliers +} + +func (le *LCREntry) GetQOSLimits() (minASR, maxASR float64, minACD, maxACD time.Duration) { + // MIN_ASR;MAX_ASR;MIN_ACD;MAX_ACD + params := strings.Split(le.StrategyParams, ";") + if len(params) == 4 { + var err error + if minASR, err = strconv.ParseFloat(params[0], 64); err != nil { + minASR = -1 + } + if maxASR, err = strconv.ParseFloat(params[1], 64); err != nil { + maxASR = -1 + } + if minACD, err = time.ParseDuration(params[2]); err != nil { + minACD = -1 + } + if maxACD, err = time.ParseDuration(params[3]); err != nil { + maxACD = -1 + } + } + return +} + type LCREntriesSorter []*LCREntry func (es LCREntriesSorter) Len() int { diff --git a/engine/loader_csv.go b/engine/loader_csv.go index 47927e74c..20049b06b 100644 --- a/engine/loader_csv.go +++ b/engine/loader_csv.go @@ -537,7 +537,7 @@ func (csvr *CSVReader) LoadRatingProfiles() (err error) { csvr.rpAliases[utils.RatingSubjectAliasKey(tenant, alias)] = subject } } - key := fmt.Sprintf("%s:%s:%s:%s", direction, tenant, tor, subject) + key := utils.ConcatenatedKey(direction, tenant, tor, subject) rp, ok := csvr.ratingProfiles[key] if !ok { rp = &RatingProfile{Id: key} @@ -878,7 +878,7 @@ func (csvr *CSVReader) LoadAccountActions() (err error) { csvr.accAliases[utils.AccountAliasKey(tenant, alias)] = account } } - tag := fmt.Sprintf("%s:%s:%s", direction, tenant, account) + tag := utils.ConcatenatedKey(direction, tenant, account) if _, alreadyDefined := csvr.accountActions[tag]; alreadyDefined { return fmt.Errorf("Duplicate account action found: %s", tag) }