diff --git a/engine/account.go b/engine/account.go index cce870291..992d8967f 100644 --- a/engine/account.go +++ b/engine/account.go @@ -146,7 +146,7 @@ func (ub *Account) debitBalanceAction(a *Action) error { } else { // add membere and save sg.MemberIds = append(sg.MemberIds, ub.Id) - accountingStorage.SetSharedGroup(sg.Id, sg) + accountingStorage.SetSharedGroup(sg) } } } diff --git a/engine/account_test.go b/engine/account_test.go index ca82447d3..645b98082 100644 --- a/engine/account_test.go +++ b/engine/account_test.go @@ -1061,7 +1061,7 @@ func TestDebitShared(t *testing.T) { sg := &SharedGroup{Id: "SG_TEST", MemberIds: []string{rif.Id, groupie.Id}, AccountParameters: map[string]*SharingParameters{"*any": &SharingParameters{Strategy: STRATEGY_MINE_RANDOM}}} accountingStorage.SetAccount(groupie) - accountingStorage.SetSharedGroup("SG_TEST", sg) + accountingStorage.SetSharedGroup(sg) cache2go.Cache(SHARED_GROUP_PREFIX+"SG_TEST", sg) err := rif.debitCreditBalance(cc, false) if err != nil { diff --git a/engine/action_timing.go b/engine/action_timing.go index 652541540..5f6e0b781 100644 --- a/engine/action_timing.go +++ b/engine/action_timing.go @@ -301,7 +301,7 @@ func (atpl ActionTimingPriotityList) Sort() { } func (at *ActionTiming) String_DISABLED() string { - return at.Tag + " " + at.GetNextStartTime(time.Now()).String() + ",w: " + strconv.FormatFloat(at.Weight, 'f', -1, 64) + return at.Id + " " + at.GetNextStartTime(time.Now()).String() + ",w: " + strconv.FormatFloat(at.Weight, 'f', -1, 64) } // Helper to remove ActionTiming members based on specific filters, empty data means no always match diff --git a/engine/calldesc.go b/engine/calldesc.go index c1497a303..1d23c2fd4 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -134,19 +134,6 @@ func (cd *CallDescriptor) AddRatingInfo(ris ...*RatingInfo) { cd.RatingInfos = append(cd.RatingInfos, ris...) } -// Returns the key used to retrive the user balance involved in this call -func (cd *CallDescriptor) GetAccountKey() string { - subj := cd.Subject - if cd.Account != "" { - // check if subject is alias - if realSubject, err := cache2go.GetCached(ACC_ALIAS_PREFIX + subj); err == nil { - cd.Account = realSubject.(string) - } - subj = cd.Account - } - return fmt.Sprintf("%s:%s:%s", cd.Direction, cd.Tenant, subj) -} - // Gets and caches the user balance information. func (cd *CallDescriptor) getAccount() (ub *Account, err error) { if cd.account == nil { @@ -295,6 +282,27 @@ func (cd *CallDescriptor) GetKey(subject string) string { return fmt.Sprintf("%s:%s:%s:%s", cd.Direction, cd.Tenant, cd.TOR, subject) } +// Returns the key used to retrive the user balance involved in this call +func (cd *CallDescriptor) GetAccountKey() string { + subj := cd.Subject + if cd.Account != "" { + // check if subject is alias + if realSubject, err := cache2go.GetCached(ACC_ALIAS_PREFIX + subj); err == nil { + cd.Account = realSubject.(string) + } + subj = cd.Account + } + 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 + } + return fmt.Sprintf("%s:%s:%s", cd.Direction, cd.Tenant, subj) +} + // Splits the received timespan into sub time spans according to the activation periods intervals. func (cd *CallDescriptor) splitInTimeSpans(firstSpan *TimeSpan) (timespans []*TimeSpan) { if firstSpan == nil { @@ -666,7 +674,7 @@ func (cd *CallDescriptor) AddRecievedCallSeconds() (err error) { func (cd *CallDescriptor) FlushCache() (err error) { cache2go.XFlush() cache2go.Flush() - dataStorage.CacheRating(nil, nil, nil, nil) + dataStorage.CacheRating(nil, nil, nil, nil, nil) accountingStorage.CacheAccounting(nil, nil, nil) return nil @@ -702,3 +710,7 @@ func (cd *CallDescriptor) Clone() *CallDescriptor { //Increments: cd.Increments, } } + +func (cd *CallDescriptor) GetLCR() []*LCRCost { + return nil +} diff --git a/engine/lcr.go b/engine/lcr.go index 3a50cb80e..fe623c0db 100644 --- a/engine/lcr.go +++ b/engine/lcr.go @@ -17,3 +17,33 @@ along with this program. If not, see */ package engine + +import ( + "fmt" + "time" +) + +type LCR struct { + Tenant string + Customer string + Direction string + LCRs []*LCREntry +} + +type LCREntry struct { + Destination string + TOR string + Strategy string + Suppliers string + ActivationTime time.Time + Weight float64 +} + +type LCRCost struct { + Supplier string + Cost float64 +} + +func (lcr *LCR) GetId() string { + return fmt.Sprintf("%s:%s:%s", lcr.Direction, lcr.Tenant, lcr.Customer) +} diff --git a/engine/loader_csv.go b/engine/loader_csv.go index 402646a82..86eac5773 100644 --- a/engine/loader_csv.go +++ b/engine/loader_csv.go @@ -219,7 +219,7 @@ func (csvr *CSVReader) WriteToDatabase(flush, verbose bool) (err error) { log.Print("Shared groups") } for k, sg := range csvr.sharedGroups { - err = accountingStorage.SetSharedGroup(k, sg) + err = accountingStorage.SetSharedGroup(sg) if err != nil { return err } diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go index ec90f6250..b36d6bd60 100644 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -181,7 +181,7 @@ func init() { csvr.LoadActionTriggers() csvr.LoadAccountActions() csvr.WriteToDatabase(false, false) - dataStorage.CacheRating(nil, nil, nil, nil) + dataStorage.CacheRating(nil, nil, nil, nil, nil) accountingStorage.CacheAccounting(nil, nil, nil) } diff --git a/engine/loader_db.go b/engine/loader_db.go index d0c54ebca..a4f7baf65 100644 --- a/engine/loader_db.go +++ b/engine/loader_db.go @@ -172,6 +172,18 @@ func (dbr *DbReader) WriteToDatabase(flush, verbose bool) (err error) { log.Println(k) } } + if verbose { + log.Print("Shared groups") + } + for k, sg := range dbr.sharedGroups { + err = accountingStorage.SetSharedGroup(sg) + if err != nil { + return err + } + if verbose { + log.Println(k) + } + } if verbose { log.Print("Actions") } diff --git a/engine/storage_interface.go b/engine/storage_interface.go index 8a7f4c0a4..3cc2e8071 100644 --- a/engine/storage_interface.go +++ b/engine/storage_interface.go @@ -41,6 +41,7 @@ const ( SHARED_GROUP_PREFIX = "shg_" ACCOUNT_PREFIX = "ubl_" DESTINATION_PREFIX = "dst_" + LCR_PREFIX = "lcr_" TEMP_DESTINATION_PREFIX = "tmp_" LOG_CALL_COST_PREFIX = "cco_" LOG_ACTION_TIMMING_PREFIX = "ltm_" @@ -71,7 +72,7 @@ Interface for storage providers. */ type RatingStorage interface { Storage - CacheRating([]string, []string, []string, []string) error + CacheRating([]string, []string, []string, []string, []string) error HasData(string, string) (bool, error) GetRatingPlan(string, bool) (*RatingPlan, error) SetRatingPlan(*RatingPlan) error @@ -82,6 +83,8 @@ type RatingStorage interface { RemoveRpAliases([]string) error GetDestination(string) (*Destination, error) SetDestination(*Destination) error + GetLCR(string, bool) (*LCR, error) + SetLCR(*LCR) error } type AccountingStorage interface { @@ -91,7 +94,7 @@ type AccountingStorage interface { GetActions(string, bool) (Actions, error) SetActions(string, Actions) error GetSharedGroup(string, bool) (*SharedGroup, error) - SetSharedGroup(string, *SharedGroup) error + SetSharedGroup(*SharedGroup) error GetAccount(string) (*Account, error) SetAccount(*Account) error GetAccAlias(string, bool) (string, error) diff --git a/engine/storage_map.go b/engine/storage_map.go index 844859f13..a1ebaf2d4 100644 --- a/engine/storage_map.go +++ b/engine/storage_map.go @@ -48,7 +48,7 @@ func (ms *MapStorage) Flush() error { return nil } -func (ms *MapStorage) CacheRating(dKeys, rpKeys, rpfKeys, alsKeys []string) error { +func (ms *MapStorage) CacheRating(dKeys, rpKeys, rpfKeys, alsKeys, lcrKeys []string) error { if dKeys == nil { cache2go.RemPrefixKey(DESTINATION_PREFIX) } @@ -61,6 +61,9 @@ func (ms *MapStorage) CacheRating(dKeys, rpKeys, rpfKeys, alsKeys []string) erro if alsKeys == nil { cache2go.RemPrefixKey(RP_ALIAS_PREFIX) } + if lcrKeys == nil { + cache2go.RemPrefixKey(LCR_PREFIX) + } for k, _ := range ms.dict { if strings.HasPrefix(k, DESTINATION_PREFIX) { if _, err := ms.GetDestination(k[len(DESTINATION_PREFIX):]); err != nil { @@ -85,6 +88,12 @@ func (ms *MapStorage) CacheRating(dKeys, rpKeys, rpfKeys, alsKeys []string) erro return err } } + if strings.HasPrefix(k, LCR_PREFIX) { + cache2go.RemKey(k) + if _, err := ms.GetLCR(k[len(LCR_PREFIX):], true); err != nil { + return err + } + } } return nil } @@ -205,6 +214,30 @@ func (ms *MapStorage) SetRatingProfile(rpf *RatingProfile) (err error) { return } +func (ms *MapStorage) GetLCR(key string, checkDb bool) (lcr *LCR, err error) { + key = LCR_PREFIX + key + if x, err := cache2go.GetCached(key); err == nil { + return x.(*LCR), nil + } + if !checkDb { + return nil, errors.New(utils.ERR_NOT_FOUND) + } + if values, ok := ms.dict[key]; ok { + err = ms.ms.Unmarshal(values, &lcr) + cache2go.Cache(key, lcr) + } else { + return nil, errors.New("not found") + } + return +} + +func (ms *MapStorage) SetLCR(lcr *LCR) (err error) { + result, err := ms.ms.Marshal(lcr) + ms.dict[LCR_PREFIX+lcr.GetId()] = result + //cache2go.Cache(LCR_PREFIX+key, lcr) + return +} + func (ms *MapStorage) GetRpAlias(key string, checkDb bool) (alias string, err error) { key = RP_ALIAS_PREFIX + key if x, err := cache2go.GetCached(key); err == nil { @@ -353,9 +386,9 @@ func (ms *MapStorage) GetSharedGroup(key string, checkDb bool) (sg *SharedGroup, return } -func (ms *MapStorage) SetSharedGroup(key string, sg *SharedGroup) (err error) { +func (ms *MapStorage) SetSharedGroup(sg *SharedGroup) (err error) { result, err := ms.ms.Marshal(sg) - ms.dict[SHARED_GROUP_PREFIX+key] = result + ms.dict[SHARED_GROUP_PREFIX+sg.Id] = result //cache2go.Cache(SHARED_GROUP_PREFIX+key, sg) return } diff --git a/engine/storage_redis.go b/engine/storage_redis.go index a8ac83288..a6e22ab5e 100644 --- a/engine/storage_redis.go +++ b/engine/storage_redis.go @@ -67,7 +67,7 @@ func (rs *RedisStorage) Flush() (err error) { return } -func (rs *RedisStorage) CacheRating(dKeys, rpKeys, rpfKeys, alsKeys []string) (err error) { +func (rs *RedisStorage) CacheRating(dKeys, rpKeys, rpfKeys, alsKeys, lcrKeys []string) (err error) { if dKeys == nil { Logger.Info("Caching all destinations") if dKeys, err = rs.db.Keys(DESTINATION_PREFIX + "*"); err != nil { @@ -121,6 +121,24 @@ func (rs *RedisStorage) CacheRating(dKeys, rpKeys, rpfKeys, alsKeys []string) (e if len(rpfKeys) != 0 { Logger.Info("Finished rating profile caching.") } + if lcrKeys == nil { + Logger.Info("Caching LCRs") + if lcrKeys, err = rs.db.Keys(LCR_PREFIX + "*"); err != nil { + return + } + cache2go.RemPrefixKey(LCR_PREFIX) + } else if len(lcrKeys) != 0 { + Logger.Info(fmt.Sprintf("Caching LCR: %v", lcrKeys)) + } + for _, key := range lcrKeys { + cache2go.RemKey(key) + if _, err = rs.GetLCR(key[len(LCR_PREFIX):], true); err != nil { + return err + } + } + if len(lcrKeys) != 0 { + Logger.Info("Finished rating profile caching.") + } if alsKeys == nil { Logger.Info("Caching rating profile aliases") if alsKeys, err = rs.db.Keys(RP_ALIAS_PREFIX + "*"); err != nil { @@ -325,6 +343,29 @@ func (rs *RedisStorage) RemoveRpAliases(accounts []string) (err error) { return } +func (rs *RedisStorage) GetLCR(key string, checkDb bool) (lcr *LCR, err error) { + key = LCR_PREFIX + key + if x, err := cache2go.GetCached(key); err == nil { + return x.(*LCR), nil + } + if !checkDb { + return nil, errors.New(utils.ERR_NOT_FOUND) + } + var values []byte + if values, err = rs.db.Get(key); err == nil { + err = rs.ms.Unmarshal(values, &lcr) + cache2go.Cache(key, lcr) + } + return +} + +func (rs *RedisStorage) SetLCR(lcr *LCR) (err error) { + result, err := rs.ms.Marshal(lcr) + err = rs.db.Set(LCR_PREFIX+lcr.GetId(), result) + cache2go.Cache(LCR_PREFIX+lcr.GetId(), lcr) + return +} + func (rs *RedisStorage) GetAccAlias(key string, checkDb bool) (alias string, err error) { key = ACC_ALIAS_PREFIX + key if x, err := cache2go.GetCached(key); err == nil { @@ -455,10 +496,10 @@ func (rs *RedisStorage) GetSharedGroup(key string, checkDb bool) (sg *SharedGrou return } -func (rs *RedisStorage) SetSharedGroup(key string, sg *SharedGroup) (err error) { +func (rs *RedisStorage) SetSharedGroup(sg *SharedGroup) (err error) { result, err := rs.ms.Marshal(sg) - err = rs.db.Set(SHARED_GROUP_PREFIX+key, result) - cache2go.Cache(SHARED_GROUP_PREFIX+key, sg) + err = rs.db.Set(SHARED_GROUP_PREFIX+sg.Id, result) + cache2go.Cache(SHARED_GROUP_PREFIX+sg.Id, sg) return } diff --git a/engine/storage_test.go b/engine/storage_test.go index e67d9e437..aa1360032 100644 --- a/engine/storage_test.go +++ b/engine/storage_test.go @@ -101,7 +101,7 @@ func TestCacheRefresh(t *testing.T) { dataStorage.SetDestination(&Destination{"T11", []string{"0"}}) dataStorage.GetDestination("T11") dataStorage.SetDestination(&Destination{"T11", []string{"1"}}) - dataStorage.CacheRating(nil, nil, nil, nil) + dataStorage.CacheRating(nil, nil, nil, nil, nil) d, err := dataStorage.GetDestination("T11") p := d.containsPrefix("1") if err != nil || p == 0 {