From 611743d3c51f31ca296244619dfb227b5cade93a Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Wed, 26 Mar 2014 11:51:03 +0200 Subject: [PATCH] first lcr algo --- cache2go/cache.go | 18 ++++++++++++++ engine/calldesc.go | 36 +++++++++++++++++++++++----- engine/lcr.go | 60 ++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 103 insertions(+), 11 deletions(-) diff --git a/cache2go/cache.go b/cache2go/cache.go index b7ab7c47e..9a85fde3f 100644 --- a/cache2go/cache.go +++ b/cache2go/cache.go @@ -206,3 +206,21 @@ func XCountEntries(prefix string) (result int) { } return } + +func GetEntriesKeys(prefix string) (keys []string) { + for key, _ := range cache { + if strings.HasPrefix(key, prefix) { + keys = append(keys, key) + } + } + return +} + +func XGetEntriesKeys(prefix string) (keys []string) { + for key, _ := range xcache { + if strings.HasPrefix(key, prefix) { + keys = append(keys, key) + } + } + return +} diff --git a/engine/calldesc.go b/engine/calldesc.go index 6471d30b8..d12d9a05b 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -296,10 +296,12 @@ func (cd *CallDescriptor) GetAccountKey() string { return fmt.Sprintf("%s:%s:%s", cd.Direction, cd.Tenant, subj) } -func (cd *CallDescriptor) GetLCRKey() string { - subj := cd.Subject - if cd.Account != "" { - subj = cd.Account +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) } @@ -713,9 +715,12 @@ func (cd *CallDescriptor) Clone() *CallDescriptor { } func (cd *CallDescriptor) GetLCR() (*LCRCost, error) { - lcr, err := dataStorage.GetLCR(cd.GetLCRKey(), false) + lcr, err := dataStorage.GetLCR(cd.GetLCRKey(""), false) if err != nil || lcr == nil { - return nil, err + // try the *any customer + if lcr, err = dataStorage.GetLCR(cd.GetLCRKey(utils.ANY), false); err != nil || lcr == nil { + return nil, err + } } lcr.Sort() lcrCost := &LCRCost{ @@ -757,6 +762,25 @@ func (cd *CallDescriptor) GetLCR() (*LCRCost, error) { } } else { // find rating profiles + ratingProfileSearchKey := fmt.Sprintf("%s:%s:%s:", lcr.Direction, lcr.Tenant, ts.Entry.TOR) + 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 { + ts.SupplierCosts = append(ts.SupplierCosts, &LCRSupplierCost{ + Supplier: supplier, + Error: err, + }) + } else { + ts.SupplierCosts = append(ts.SupplierCosts, &LCRSupplierCost{ + Supplier: supplier, + Cost: cc.Cost, + }) + } + } // sort according to strategy ts.Sort() } diff --git a/engine/lcr.go b/engine/lcr.go index f6b5339a7..1261e7da5 100644 --- a/engine/lcr.go +++ b/engine/lcr.go @@ -22,6 +22,9 @@ import ( "fmt" "sort" "time" + + "github.com/cgrates/cgrates/cache2go" + "github.com/cgrates/cgrates/utils" ) const ( @@ -41,10 +44,12 @@ type LCRActivation struct { Entries []*LCREntry } type LCREntry struct { - Destination string - TOR string - Strategy string - Suppliers string + DestinationId string + TOR string + Strategy string + Suppliers string + Weight float64 + precision int } type LCRCost struct { @@ -83,7 +88,52 @@ func (lcr *LCR) Sort() { sort.Sort(lcr) } -func (lcra *LCRActivation) GetLCREntryForPrefix(prefix string) *LCREntry { +type LCREntriesSorter []*LCREntry + +func (es LCREntriesSorter) Len() int { + return len(es) +} + +func (es LCREntriesSorter) Swap(i, j int) { + es[i], es[j] = es[j], es[i] +} + +func (es LCREntriesSorter) Less(j, i int) bool { + return es[i].precision < es[j].precision || + (es[i].precision == es[j].precision && es[i].Weight < es[j].Weight) + +} + +func (es LCREntriesSorter) Sort() { + sort.Sort(es) +} + +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 { + for _, entry := range lcra.Entries { + if entry.DestinationId == dId { + entry.precision = len(p) + potentials = append(potentials, entry) + } + } + } + } + } + if len(potentials) > 0 { + // sort by precision and weight + potentials.Sort() + return potentials[0] + } + // return the *any entry if it exists + for _, entry := range lcra.Entries { + if entry.DestinationId == utils.ANY { + return entry + } + } return nil }