// getSessionIDsMatchingIndexes will check inside indexes if it can find sessionIDs matching all filters // matchedIndexes returns map[matchedFieldName]possibleMatchedFieldVal so we optimize further to avoid checking them func (smg *SMGeneric) getSessionIDsMatchingIndexes(fltrs map[string]string) (utils.StringMap, map[string]string) { smg.aSIMux.RLock() defer smg.aSIMux.RUnlock() sessionIDxes := smg.aSessionsIndex // Clone here and unlock sooner if getting slow matchedIndexes := make(map[string]string) var matchingSessions utils.StringMap checkNr := 0 for fltrName, fltrVal := range fltrs { checkNr += 1 if _, hasFldName := sessionIDxes[fltrName]; !hasFldName { continue } if _, hasFldVal := sessionIDxes[fltrName][fltrVal]; !hasFldVal { matchedIndexes[fltrName] = utils.META_NONE continue } matchedIndexes[fltrName] = fltrVal if checkNr == 1 { // First run will init the MatchingSessions matchingSessions = sessionIDxes[fltrName][fltrVal] continue } // Higher run, takes out non matching indexes for sessID := range sessionIDxes[fltrName][fltrVal] { if _, hasUUID := matchingSessions[sessID]; !hasUUID { delete(matchingSessions, sessID) } } } return matchingSessions.Clone(), matchedIndexes }
// sets all the fields of the balance func (acc *Account) setBalanceAction(a *Action) error { if a == nil { return errors.New("nil action") } if acc.BalanceMap == nil { acc.BalanceMap = make(map[string]Balances) } var balance *Balance var found bool var previousSharedGroups utils.StringMap // kept for comparison if a.Balance.Uuid != nil && *a.Balance.Uuid != "" { // balance uuid match for balanceType := range acc.BalanceMap { for _, b := range acc.BalanceMap[balanceType] { if b.Uuid == *a.Balance.Uuid && !b.IsExpired() { previousSharedGroups = b.SharedGroups balance = b found = true break // only set one balance } } if found { break } } if !found { return fmt.Errorf("cannot find balance with uuid: <%s>", *a.Balance.Uuid) } } else { // balance id match for balanceType := range acc.BalanceMap { for _, b := range acc.BalanceMap[balanceType] { if a.Balance.ID != nil && b.ID == *a.Balance.ID && !b.IsExpired() { previousSharedGroups = b.SharedGroups balance = b found = true break // only set one balance } } if found { break } } // if it is not found then we create it if !found { if a.Balance.Type == nil { // cannot create the entry in the balance map without this info return errors.New("missing balance type") } balance = &Balance{} balance.Uuid = utils.GenUUID() // alway overwrite the uuid for consistency acc.BalanceMap[*a.Balance.Type] = append(acc.BalanceMap[*a.Balance.Type], balance) } } if a.Balance.ID != nil && *a.Balance.ID == utils.META_DEFAULT { // treat it separately since modifyBalance sets expiry and others parameters, not specific for *default if a.Balance.Value != nil { balance.ID = *a.Balance.ID balance.Value = a.Balance.GetValue() balance.SetDirty() // Mark the balance as dirty since we have modified and it should be checked by action triggers } } else { a.Balance.ModifyBalance(balance) } // modify if necessary the shared groups here if !found || !previousSharedGroups.Equal(balance.SharedGroups) { _, err := Guardian.Guard(func() (interface{}, error) { sgs := make([]string, len(balance.SharedGroups)) i := 0 for sgID := range balance.SharedGroups { // add shared group member sg, err := ratingStorage.GetSharedGroup(sgID, false, utils.NonTransactional) if err != nil || sg == nil { //than is problem utils.Logger.Warning(fmt.Sprintf("Could not get shared group: %v", sgID)) } else { if _, found := sg.MemberIds[acc.ID]; !found { // add member and save if sg.MemberIds == nil { sg.MemberIds = make(utils.StringMap) } sg.MemberIds[acc.ID] = true ratingStorage.SetSharedGroup(sg, utils.NonTransactional) } } i++ } ratingStorage.CacheDataFromDB(utils.SHARED_GROUP_PREFIX, sgs, true) return 0, nil }, 0, balance.SharedGroups.Slice()...) if err != nil { return err } } acc.InitCounters() acc.ExecuteActionTriggers(nil) return nil }
// sets all the fields of the balance func (acc *Account) setBalanceAction(a *Action) error { if a == nil { return errors.New("nil action") } if a.Balance.Type == nil { return errors.New("missing balance type") } balanceType := *a.Balance.Type if acc.BalanceMap == nil { acc.BalanceMap = make(map[string]Balances, 1) } var previousSharedGroups utils.StringMap // kept for comparison var balance *Balance var found bool for _, b := range acc.BalanceMap[balanceType] { if b.IsExpired() { continue } if (a.Balance.Uuid != nil && b.Uuid == *a.Balance.Uuid) || (a.Balance.ID != nil && b.ID == *a.Balance.ID) { previousSharedGroups = b.SharedGroups balance = b found = true break // only set one balance } } // if it is not found then we add it to the list if balance == nil { balance = &Balance{} balance.Uuid = utils.GenUUID() // alway overwrite the uuid for consistency acc.BalanceMap[balanceType] = append(acc.BalanceMap[balanceType], balance) } if a.Balance.ID != nil && *a.Balance.ID == utils.META_DEFAULT { balance.ID = utils.META_DEFAULT if a.Balance.Value != nil { balance.Value = a.Balance.GetValue() } } else { a.Balance.ModifyBalance(balance) } if !found || !previousSharedGroups.Equal(balance.SharedGroups) { _, err := Guardian.Guard(func() (interface{}, error) { for sgID := range balance.SharedGroups { // add shared group member sg, err := ratingStorage.GetSharedGroup(sgID, false, utils.NonTransactional) if err != nil || sg == nil { //than is problem utils.Logger.Warning(fmt.Sprintf("Could not get shared group: %v", sgID)) } else { if _, found := sg.MemberIds[acc.ID]; !found { // add member and save if sg.MemberIds == nil { sg.MemberIds = make(utils.StringMap) } sg.MemberIds[acc.ID] = true ratingStorage.SetSharedGroup(sg, utils.NonTransactional) } } } return 0, nil }, 0, balance.SharedGroups.Slice()...) if err != nil { return err } } acc.InitCounters() acc.ExecuteActionTriggers(nil) return nil }
func (self *ApierV1) SetBalance(attr *AttrSetBalance, reply *string) error { if missing := utils.MissingStructFields(attr, []string{"Tenant", "Account", "BalanceType"}); len(missing) != 0 { return utils.NewErrMandatoryIeMissing(missing...) } if (attr.BalanceID == nil || *attr.BalanceID == "") && (attr.BalanceUUID == nil || *attr.BalanceUUID == "") { return utils.NewErrMandatoryIeMissing("BalanceID", "or", "BalanceUUID") } var err error if attr.ExpiryTime != nil { attr.expTime, err = utils.ParseTimeDetectLayout(*attr.ExpiryTime, self.Config.DefaultTimezone) if err != nil { *reply = err.Error() return err } } accID := utils.ConcatenatedKey(attr.Tenant, attr.Account) _, err = engine.Guardian.Guard(func() (interface{}, error) { account, err := self.AccountDb.GetAccount(accID) if err != nil { return 0, utils.ErrNotFound } if account.BalanceMap == nil { account.BalanceMap = make(map[string]engine.BalanceChain, 1) } var previousSharedGroups utils.StringMap // kept for comparison var balance *engine.Balance var found bool for _, b := range account.BalanceMap[attr.BalanceType] { if b.IsExpired() { continue } if (attr.BalanceUUID != nil && b.Uuid == *attr.BalanceUUID) || (attr.BalanceID != nil && b.Id == *attr.BalanceID) { previousSharedGroups = b.SharedGroups balance = b found = true break // only set one balance } } // if it is not found then we add it to the list if balance == nil { balance = &engine.Balance{} balance.Uuid = utils.GenUUID() // alway overwrite the uuid for consistency account.BalanceMap[attr.BalanceType] = append(account.BalanceMap[attr.BalanceType], balance) } if attr.BalanceID != nil && *attr.BalanceID == utils.META_DEFAULT { balance.Id = utils.META_DEFAULT if attr.Value != nil { balance.Value = *attr.Value } } else { attr.SetBalance(balance) } if !found || !previousSharedGroups.Equal(balance.SharedGroups) { _, err = engine.Guardian.Guard(func() (interface{}, error) { for sgID := range balance.SharedGroups { // add shared group member sg, err := self.RatingDb.GetSharedGroup(sgID, false) if err != nil || sg == nil { //than is problem utils.Logger.Warning(fmt.Sprintf("Could not get shared group: %v", sgID)) } else { if _, found := sg.MemberIds[account.Id]; !found { // add member and save if sg.MemberIds == nil { sg.MemberIds = make(utils.StringMap) } sg.MemberIds[account.Id] = true self.RatingDb.SetSharedGroup(sg) } } } return 0, nil }, 0, balance.SharedGroups.Slice()...) } account.InitCounters() account.ExecuteActionTriggers(nil) self.AccountDb.SetAccount(account) return 0, nil }, 0, accID) if err != nil { *reply = err.Error() return err } *reply = utils.OK return nil }