// Returns the aliases of one specific account on a tenant func (rs *RedisStorage) GetAccountAliases(tenant, account string, skipCache bool) (aliases []string, err error) { tenantPrfx := ACC_ALIAS_PREFIX + tenant + utils.CONCATENATED_KEY_SEP var alsKeys []string if !skipCache { alsKeys = cache2go.GetEntriesKeys(tenantPrfx) } if len(alsKeys) == 0 { if alsKeys, err = rs.db.Keys(tenantPrfx + "*"); err != nil { return nil, err } } for _, key := range alsKeys { if alsAcnt, err := rs.GetAccAlias(key[len(ACC_ALIAS_PREFIX):], skipCache); err != nil { return nil, err } else if alsAcnt == account { alsFromKey := key[len(tenantPrfx):] // take out the alias out of key+tenant aliases = append(aliases, alsFromKey) } } return aliases, nil }
func (ms *MapStorage) GetRPAliases(tenant, subject string, skipCache bool) (aliases []string, err error) { tenantPrfx := RP_ALIAS_PREFIX + tenant + utils.CONCATENATED_KEY_SEP var alsKeys []string if !skipCache { alsKeys = cache2go.GetEntriesKeys(tenantPrfx) } for _, key := range alsKeys { if alsSubj, err := ms.GetRpAlias(key[len(RP_ALIAS_PREFIX):], skipCache); err != nil { return nil, err } else if alsSubj == subject { alsFromKey := key[len(tenantPrfx):] // take out the alias out of key+tenant aliases = append(aliases, alsFromKey) } } if len(alsKeys) == 0 { for key, value := range ms.dict { if strings.HasPrefix(key, RP_ALIAS_PREFIX) && len(key) >= len(tenantPrfx) && key[:len(tenantPrfx)] == tenantPrfx && subject == string(value) { aliases = append(aliases, key[len(tenantPrfx):]) } } } return aliases, nil }
func (cd *CallDescriptor) GetLCR(stats StatsInterface, p *utils.Paginator) (*LCRCost, error) { cd.account = nil // make sure it's not cached lcr, err := cd.GetLCRFromStorage() if err != nil { return nil, err } // sort by activation time lcr.Sort() // find if one ore more entries apply to this cd (create lcr timespans) // create timespans and attach lcr entries to them lcrCost := &LCRCost{} for _, lcrActivation := range lcr.Activations { //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.Entry = lcrEntry } else { // because lcr is sorted the folowing ones will // only activate later than cd.Timestart break } } if lcrCost.Entry == nil { return lcrCost, nil } //log.Printf("Entry: %+v", lcrCost.Entry) if lcrCost.Entry.Strategy == LCR_STRATEGY_STATIC { for _, supplier := range lcrCost.Entry.GetParams() { lcrCD := cd.Clone() lcrCD.Account = supplier lcrCD.Subject = supplier lcrCD.Category = lcrCost.Entry.RPCategory fullSupplier := utils.ConcatenatedKey(lcrCD.Direction, lcrCD.Tenant, lcrCD.Category, lcrCD.Subject) var cc *CallCost var err error if cd.account, err = accountingStorage.GetAccount(lcrCD.GetAccountKey()); err == nil { if cd.account.Disabled { lcrCost.SupplierCosts = append(lcrCost.SupplierCosts, &LCRSupplierCost{ Supplier: fullSupplier, Error: fmt.Sprintf("supplier %s is disabled", supplier), }) continue } cc, err = lcrCD.debit(cd.account, true, true) } else { cc, err = lcrCD.GetCost() } //log.Printf("CC: %+v", cc.Timespans[0].ratingInfo.RateIntervals[0].Rating.Rates[0]) if err != nil || cc == nil { lcrCost.SupplierCosts = append(lcrCost.SupplierCosts, &LCRSupplierCost{ Supplier: fullSupplier, Error: err.Error(), }) } else { lcrCost.SupplierCosts = append(lcrCost.SupplierCosts, &LCRSupplierCost{ Supplier: fullSupplier, Cost: cc.Cost, Duration: cc.GetDuration(), }) } } } else { // find rating profiles category := lcrCost.Entry.RPCategory if category == utils.META_DEFAULT { category = lcr.Category } ratingProfileSearchKey := utils.ConcatenatedKey(lcr.Direction, lcr.Tenant, lcrCost.Entry.RPCategory) //log.Print("KEY: ", ratingProfileSearchKey) suppliers := cache2go.GetEntriesKeys(utils.RATING_PROFILE_PREFIX + ratingProfileSearchKey) for _, supplier := range suppliers { //log.Print("Supplier: ", supplier) split := strings.Split(supplier, ":") supplier = split[len(split)-1] lcrCD := cd.Clone() lcrCD.Category = category lcrCD.Account = supplier lcrCD.Subject = supplier fullSupplier := utils.ConcatenatedKey(lcrCD.Direction, lcrCD.Tenant, lcrCD.Category, lcrCD.Subject) var qosSortParams []string var asrValues sort.Float64Slice var pddValues sort.Float64Slice var acdValues sort.Float64Slice var tcdValues sort.Float64Slice var accValues sort.Float64Slice var tccValues sort.Float64Slice var ddcValues sort.Float64Slice // track if one value is never calculated asrNeverConsidered := true pddNeverConsidered := true acdNeverConsidered := true tcdNeverConsidered := true accNeverConsidered := true tccNeverConsidered := true ddcNeverConsidered := true if utils.IsSliceMember([]string{LCR_STRATEGY_QOS, LCR_STRATEGY_QOS_THRESHOLD, LCR_STRATEGY_LOAD}, lcrCost.Entry.Strategy) { if stats == nil { lcrCost.SupplierCosts = append(lcrCost.SupplierCosts, &LCRSupplierCost{ Supplier: fullSupplier, Error: fmt.Sprintf("Cdr stats service not configured"), }) continue } rpfKey := utils.ConcatenatedKey(ratingProfileSearchKey, supplier) if rpf, err := ratingStorage.GetRatingProfile(rpfKey, false); err != nil { lcrCost.SupplierCosts = append(lcrCost.SupplierCosts, &LCRSupplierCost{ Supplier: fullSupplier, Error: fmt.Sprintf("Rating plan error: %s", err.Error()), }) continue } else if rpf != nil { rpf.RatingPlanActivations.Sort() activeRas := rpf.RatingPlanActivations.GetActiveForCall(cd) var cdrStatsQueueIds []string for _, ra := range activeRas { for _, qId := range ra.CdrStatQueueIds { if qId != "" { cdrStatsQueueIds = append(cdrStatsQueueIds, qId) } } } statsErr := false var supplierQueues []*StatsQueue for _, qId := range cdrStatsQueueIds { if lcrCost.Entry.Strategy == LCR_STRATEGY_LOAD { for _, qId := range cdrStatsQueueIds { sq := &StatsQueue{} if err := stats.GetQueue(qId, sq); err == nil { if sq.conf.QueueLength == 0 { //only add qeues that don't have fixed length supplierQueues = append(supplierQueues, sq) } } } } else { statValues := make(map[string]float64) if err := stats.GetValues(qId, &statValues); err != nil { lcrCost.SupplierCosts = append(lcrCost.SupplierCosts, &LCRSupplierCost{ Supplier: fullSupplier, Error: fmt.Sprintf("Get stats values for queue id %s, error %s", qId, err.Error()), }) statsErr = true break } if asr, exists := statValues[ASR]; exists { if asr > STATS_NA { asrValues = append(asrValues, asr) } asrNeverConsidered = false } if pdd, exists := statValues[PDD]; exists { if pdd > STATS_NA { pddValues = append(pddValues, pdd) } pddNeverConsidered = false } if acd, exists := statValues[ACD]; exists { if acd > STATS_NA { acdValues = append(acdValues, acd) } acdNeverConsidered = false } if tcd, exists := statValues[TCD]; exists { if tcd > STATS_NA { tcdValues = append(tcdValues, tcd) } tcdNeverConsidered = false } if acc, exists := statValues[ACC]; exists { if acc > STATS_NA { accValues = append(accValues, acc) } accNeverConsidered = false } if tcc, exists := statValues[TCC]; exists { if tcc > STATS_NA { tccValues = append(tccValues, tcc) } tccNeverConsidered = false } if ddc, exists := statValues[TCC]; exists { if ddc > STATS_NA { ddcValues = append(ddcValues, ddc) } ddcNeverConsidered = false } } } if lcrCost.Entry.Strategy == LCR_STRATEGY_LOAD { if len(supplierQueues) > 0 { lcrCost.SupplierCosts = append(lcrCost.SupplierCosts, &LCRSupplierCost{ Supplier: fullSupplier, supplierQueues: supplierQueues, }) } continue // next supplier } if statsErr { // Stats error in loop, to go next supplier continue } asrValues.Sort() pddValues.Sort() acdValues.Sort() tcdValues.Sort() accValues.Sort() tccValues.Sort() ddcValues.Sort() //log.Print(asrValues, acdValues) if utils.IsSliceMember([]string{LCR_STRATEGY_QOS_THRESHOLD, LCR_STRATEGY_QOS}, lcrCost.Entry.Strategy) { qosSortParams = lcrCost.Entry.GetParams() } if lcrCost.Entry.Strategy == LCR_STRATEGY_QOS_THRESHOLD { // filter suppliers by qos thresholds asrMin, asrMax, pddMin, pddMax, acdMin, acdMax, tcdMin, tcdMax, accMin, accMax, tccMin, tccMax, ddcMin, ddcMax := lcrCost.Entry.GetQOSLimits() //log.Print(asrMin, asrMax, acdMin, acdMax) // skip current supplier if off limits if asrMin > 0 && len(asrValues) != 0 && asrValues[0] < asrMin { continue } if asrMax > 0 && len(asrValues) != 0 && asrValues[len(asrValues)-1] > asrMax { continue } if pddMin > 0 && len(pddValues) != 0 && pddValues[0] < pddMin.Seconds() { continue } if pddMax > 0 && len(pddValues) != 0 && pddValues[len(pddValues)-1] > pddMax.Seconds() { continue } if acdMin > 0 && len(acdValues) != 0 && acdValues[0] < acdMin.Seconds() { continue } if acdMax > 0 && len(acdValues) != 0 && acdValues[len(acdValues)-1] > acdMax.Seconds() { continue } if tcdMin > 0 && len(tcdValues) != 0 && tcdValues[0] < tcdMin.Seconds() { continue } if tcdMax > 0 && len(tcdValues) != 0 && tcdValues[len(tcdValues)-1] > tcdMax.Seconds() { continue } if accMin > 0 && len(accValues) != 0 && accValues[0] < accMin { continue } if accMax > 0 && len(accValues) != 0 && accValues[len(accValues)-1] > accMax { continue } if tccMin > 0 && len(tccValues) != 0 && tccValues[0] < tccMin { continue } if tccMax > 0 && len(tccValues) != 0 && tccValues[len(tccValues)-1] > tccMax { continue } if ddcMin > 0 && len(ddcValues) != 0 && ddcValues[0] < ddcMin { continue } if ddcMax > 0 && len(ddcValues) != 0 && ddcValues[len(ddcValues)-1] > ddcMax { continue } } } } var cc *CallCost var err error //log.Print("CD: ", lcrCD.GetAccountKey()) if cd.account, err = accountingStorage.GetAccount(lcrCD.GetAccountKey()); err == nil { //log.Print("ACCCOUNT") if cd.account.Disabled { lcrCost.SupplierCosts = append(lcrCost.SupplierCosts, &LCRSupplierCost{ Supplier: fullSupplier, Error: fmt.Sprintf("supplier %s is disabled", supplier), }) continue } cc, err = lcrCD.debit(cd.account, true, true) } else { //log.Print("STANDARD") cc, err = lcrCD.GetCost() } //log.Printf("CC: %+v", cc) if err != nil || cc == nil { lcrCost.SupplierCosts = append(lcrCost.SupplierCosts, &LCRSupplierCost{ Supplier: fullSupplier, Error: err.Error(), }) continue } else { supplCost := &LCRSupplierCost{ Supplier: fullSupplier, Cost: cc.Cost, Duration: cc.GetDuration(), } qos := make(map[string]float64, 5) if !asrNeverConsidered { qos[ASR] = utils.AvgNegative(asrValues) } if !pddNeverConsidered { qos[PDD] = utils.AvgNegative(pddValues) } if !acdNeverConsidered { qos[ACD] = utils.AvgNegative(acdValues) } if !tcdNeverConsidered { qos[TCD] = utils.AvgNegative(tcdValues) } if !accNeverConsidered { qos[ACC] = utils.AvgNegative(accValues) } if !tccNeverConsidered { qos[TCC] = utils.AvgNegative(tccValues) } if !ddcNeverConsidered { qos[DDC] = utils.AvgNegative(ddcValues) } if utils.IsSliceMember([]string{LCR_STRATEGY_QOS, LCR_STRATEGY_QOS_THRESHOLD}, lcrCost.Entry.Strategy) { supplCost.QOS = qos supplCost.qosSortParams = qosSortParams } lcrCost.SupplierCosts = append(lcrCost.SupplierCosts, supplCost) } } // sort according to strategy lcrCost.Sort() } if p != nil { if p.Offset != nil && *p.Offset > 0 && *p.Offset < len(lcrCost.SupplierCosts) { lcrCost.SupplierCosts = lcrCost.SupplierCosts[*p.Offset:] } if p.Limit != nil && *p.Limit > 0 && *p.Limit < len(lcrCost.SupplierCosts) { lcrCost.SupplierCosts = lcrCost.SupplierCosts[:*p.Limit] } } return lcrCost, nil }
func (cd *CallDescriptor) GetLCR() (*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 { return nil, err } } lcr.Sort() lcrCost := &LCRCost{ TimeSpans: []*LCRTimeSpan{&LCRTimeSpan{StartTime: cd.TimeStart}}, } for _, lcrActivation := range lcr.Activations { // TODO: filer entry by destination lcrEntry := lcrActivation.GetLCREntryForPrefix(cd.Destination) if lcrActivation.ActivationTime.Before(cd.TimeStart) || lcrActivation.ActivationTime.Equal(cd.TimeStart) { lcrCost.TimeSpans[0].Entry = lcrEntry } else { if lcrActivation.ActivationTime.Before(cd.TimeEnd) { // add lcr timespan lcrCost.TimeSpans = append(lcrCost.TimeSpans, &LCRTimeSpan{ StartTime: lcrActivation.ActivationTime, Entry: lcrEntry, }) } } } for _, ts := range lcrCost.TimeSpans { if ts.Entry.Strategy == LCR_STRATEGY_STATIC { for _, supplier := range strings.Split(ts.Entry.Suppliers, ";") { supplier = strings.TrimSpace(supplier) 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, }) } } } else { // find rating profiles ratingProfileSearchKey := fmt.Sprintf("%s:%s:%s:", lcr.Direction, lcr.Tenant, ts.Entry.Category) 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() } } return lcrCost, nil }
// Index cached ResourceLimits with MetaString filter types func (rls *ResourceLimiterService) indexStringFilters(rlIDs []string) error { utils.Logger.Info("<RLs> Start indexing string filters") newStringIndexes := make(map[string]map[string]utils.StringMap) // Index it transactional var cacheIDsToIndex []string // Cache keys of RLs to be indexed if rlIDs == nil { cacheIDsToIndex = cache2go.GetEntriesKeys(utils.ResourceLimitsPrefix) } else { for _, rlID := range rlIDs { cacheIDsToIndex = append(cacheIDsToIndex, utils.ResourceLimitsPrefix+rlID) } } for _, cacheKey := range cacheIDsToIndex { x, ok := cache2go.Get(cacheKey) if !ok { return utils.ErrNotFound } rl := x.(*ResourceLimit) var hasMetaString bool for _, fltr := range rl.Filters { if fltr.Type != MetaString { continue } hasMetaString = true // Mark that we found at least one metatring so we don't need to index globally if _, hastIt := newStringIndexes[fltr.FieldName]; !hastIt { newStringIndexes[fltr.FieldName] = make(map[string]utils.StringMap) } for _, fldVal := range fltr.Values { if _, hasIt := newStringIndexes[fltr.FieldName][fldVal]; !hasIt { newStringIndexes[fltr.FieldName][fldVal] = make(utils.StringMap) } newStringIndexes[fltr.FieldName][fldVal][rl.ID] = true } } if !hasMetaString { if _, hasIt := newStringIndexes[utils.NOT_AVAILABLE]; !hasIt { newStringIndexes[utils.NOT_AVAILABLE] = make(map[string]utils.StringMap) } if _, hasIt := newStringIndexes[utils.NOT_AVAILABLE][utils.NOT_AVAILABLE]; !hasIt { newStringIndexes[utils.NOT_AVAILABLE][utils.NOT_AVAILABLE] = make(utils.StringMap) } newStringIndexes[utils.NOT_AVAILABLE][utils.NOT_AVAILABLE][rl.ID] = true // Fields without real field index will be located in map[NOT_AVAILABLE][NOT_AVAILABLE][rl.ID] } } rls.Lock() defer rls.Unlock() if rlIDs == nil { // We have rebuilt complete index rls.stringIndexes = newStringIndexes return nil } // Merge the indexes since we have only performed limited indexing for fldNameKey, mpFldName := range newStringIndexes { if _, hasIt := rls.stringIndexes[fldNameKey]; !hasIt { rls.stringIndexes[fldNameKey] = mpFldName } else { for fldValKey, strMap := range newStringIndexes[fldNameKey] { if _, hasIt := rls.stringIndexes[fldNameKey][fldValKey]; !hasIt { rls.stringIndexes[fldNameKey][fldValKey] = strMap } else { for resIDKey := range newStringIndexes[fldNameKey][fldValKey] { rls.stringIndexes[fldNameKey][fldValKey][resIDKey] = true } } } } } utils.Logger.Info("<RLs> Done indexing string filters") return nil }