From bfe866d57c5896f997e370b1e93bfb990938f5e6 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Mon, 10 Aug 2015 16:07:43 +0300 Subject: [PATCH] passing engine tests --- engine/aliases.go | 69 ++++++++++++++++++++++++++++++++++++--- engine/calldesc.go | 21 +++++++----- engine/calldesc_test.go | 1 + engine/loader_csv_test.go | 15 ++++++--- engine/models.go | 4 +-- engine/storage_csv.go | 2 +- engine/storage_map.go | 7 ++-- engine/storage_redis.go | 7 ++-- 8 files changed, 100 insertions(+), 26 deletions(-) diff --git a/engine/aliases.go b/engine/aliases.go index f812efba9..e4c89396c 100644 --- a/engine/aliases.go +++ b/engine/aliases.go @@ -5,6 +5,7 @@ import ( "strings" "sync" + "github.com/cgrates/cgrates/cache2go" "github.com/cgrates/cgrates/utils" "github.com/cgrates/rpcclient" ) @@ -35,7 +36,7 @@ func (avs AliasValues) Swap(i, j int) { avs[i], avs[j] = avs[j], avs[i] } -func (avs AliasValues) Less(j, i int) bool { // get higher ponder in front +func (avs AliasValues) Less(j, i int) bool { // get higher weight in front return avs[i].Weight < avs[j].Weight } @@ -43,6 +44,24 @@ func (avs AliasValues) Sort() { sort.Sort(avs) } +// returns a mapping between aliases and destination ids in a slice sorted by weights +func (avs AliasValues) GetWeightSlice() (result []map[string][]string) { + avs.Sort() + prevWeight := -1.0 + for _, value := range avs { + var m map[string][]string + if value.Weight != prevWeight { + // start a new map + m = make(map[string][]string) + result = append(result, m) + } else { + m = result[len(result)-1] + } + m[value.Alias] = append(m[value.Alias], value.DestinationId) + } + return +} + func (al *Alias) GetId() string { return utils.ConcatenatedKey(al.Direction, al.Tenant, al.Category, al.Account, al.Subject, al.Group) } @@ -75,7 +94,7 @@ func (al *Alias) SetId(id string) error { type AliasService interface { SetAlias(Alias, *string) error RemoveAlias(Alias, *string) error - GetAliases(Alias, *[]*Alias) error + GetAlias(Alias, *Alias) error ReloadAliases(string, *string) error } @@ -104,7 +123,6 @@ func newAliasMap(accountingDb AccountingStorage) *AliasMap { func (am *AliasMap) ReloadAliases(in string, reply *string) error { am.mu.Lock() defer am.mu.Unlock() - // backup old data oldTable := am.table am.table = make(map[string]AliasValues) @@ -154,7 +172,9 @@ func (am *AliasMap) GetAlias(al Alias, result *Alias) error { am.mu.RLock() defer am.mu.RUnlock() variants := al.GenerateIds() + //log.Print("TABLE: ", am.table) for _, variant := range variants { + //log.Printf("AL %+v", variant) if r, ok := am.table[variant]; ok { al.Values = r *result = al @@ -184,10 +204,49 @@ func (ps *ProxyAliasService) RemoveAlias(al Alias, reply *string) error { return ps.Client.Call("AliasV1.RemoveAlias", al, reply) } -func (ps *ProxyAliasService) GetAlias(al Alias, aliases *Alias) error { - return ps.Client.Call("AliasV1.GetAliases", al, aliases) +func (ps *ProxyAliasService) GetAlias(al Alias, alias *Alias) error { + return ps.Client.Call("AliasV1.GetAliases", al, alias) } func (ps *ProxyAliasService) ReloadAliases(in string, reply *string) error { return ps.Client.Call("AliasV1.ReloadAliases", in, reply) } + +func GetBestAlias(destination, direction, tenant, category, account, subject, group string) (string, error) { + if aliasService == nil { + return "", nil + } + response := Alias{} + if err := aliasService.GetAlias(Alias{ + Direction: direction, + Tenant: tenant, + Category: category, + Account: account, + Subject: subject, + Group: group, + }, &response); err != nil { + return "", err + } + // sort according to weight + values := response.Values.GetWeightSlice() + // check destination ids + + for _, p := range utils.SplitPrefix(destination, MIN_PREFIX_MATCH) { + if x, err := cache2go.GetCached(utils.DESTINATION_PREFIX + p); err == nil { + for _, aliasMap := range values { + for alias, aliasDestIds := range aliasMap { + destIds := x.(map[interface{}]struct{}) + for idId := range destIds { + dId := idId.(string) + for _, aliasDestId := range aliasDestIds { + if aliasDestId == utils.ANY || aliasDestId == dId { + return alias, nil + } + } + } + } + } + } + } + return "", utils.ErrNotFound +} diff --git a/engine/calldesc.go b/engine/calldesc.go index a7d788515..cc7a97c71 100644 --- a/engine/calldesc.go +++ b/engine/calldesc.go @@ -69,6 +69,7 @@ var ( historyScribe history.Scribe pubSubServer PublisherSubscriber userService UserService + aliasService AliasService ) // Exported method to set the storage getter. @@ -112,6 +113,10 @@ func SetUserService(us UserService) { userService = us } +func SetAliasService(as AliasService) { + aliasService = as +} + func Publish(event CgrEvent) { if pubSubServer != nil { var s string @@ -297,11 +302,10 @@ func (cd *CallDescriptor) addRatingInfos(ris RatingInfos) bool { // The prefixLen is limiting the length of the destination prefix. func (cd *CallDescriptor) GetKey(subject string) string { // check if subject is alias - /*if rs, err := cache2go.GetCached(utils.RP_ALIAS_PREFIX + utils.RatingSubjectAliasKey(cd.Tenant, subject)); err == nil { - realSubject := rs.(string) - subject = realSubject - cd.Subject = realSubject - }*/ + if alias, err := GetBestAlias(cd.Destination, cd.Direction, cd.Tenant, cd.Category, cd.Account, cd.Subject, utils.ALIAS_GROUP_RP); err == nil && alias != "" { + subject = alias + cd.Subject = alias + } return utils.ConcatenatedKey(cd.Direction, cd.Tenant, cd.Category, subject) } @@ -310,9 +314,10 @@ func (cd *CallDescriptor) GetAccountKey() string { subj := cd.Subject if cd.Account != "" { // check if subject is alias - /*if realSubject, err := cache2go.GetCached(utils.ACC_ALIAS_PREFIX + utils.AccountAliasKey(cd.Tenant, subj)); err == nil { - cd.Account = realSubject.(string) - }*/ + alias, err := GetBestAlias(cd.Destination, cd.Direction, cd.Tenant, cd.Category, cd.Account, cd.Subject, utils.ALIAS_GROUP_ACC) + if err == nil && alias != "" { + cd.Account = alias + } subj = cd.Account } return utils.ConcatenatedKey(cd.Direction, cd.Tenant, subj) diff --git a/engine/calldesc_test.go b/engine/calldesc_test.go index 8ac3f708f..4cc69a207 100644 --- a/engine/calldesc_test.go +++ b/engine/calldesc_test.go @@ -616,6 +616,7 @@ func TestGetCostWithMaxCostFree(t *testing.T) { } func TestMaxSessionTimeWithAccountAlias(t *testing.T) { + aliasService, _ = NewAliasMap(accountingStorage) cd := &CallDescriptor{ TimeStart: time.Date(2013, 10, 21, 18, 34, 0, 0, time.UTC), TimeEnd: time.Date(2013, 10, 21, 18, 35, 0, 0, time.UTC), diff --git a/engine/loader_csv_test.go b/engine/loader_csv_test.go index 88f40a90c..9fce36751 100644 --- a/engine/loader_csv_test.go +++ b/engine/loader_csv_test.go @@ -122,7 +122,7 @@ ANY_PLAN,DATA_RATE,*any,10 *out,vdf,0,rif,2012-01-01T00:00:00Z,EVENING,, *out,vdf,call,rif,2012-02-28T00:00:00Z,EVENING,, *out,vdf,call,dan,2012-01-01T00:00:00Z,EVENING,, -*out,vdf,0,minu;a1;a2;a3,2012-01-01T00:00:00Z,EVENING,, +*out,vdf,0,minu,2012-01-01T00:00:00Z,EVENING,, *out,vdf,0,*any,2012-02-28T00:00:00Z,EVENING,, *out,vdf,0,one,2012-02-28T00:00:00Z,STANDARD,, *out,vdf,0,inf,2012-02-28T00:00:00Z,STANDARD,inf, @@ -187,7 +187,7 @@ CDRST2_WARN_ASR,,*min_asr,30,true,0,,,,,,,,,,,5,CDRST_WARN_HTTP,10 CDRST2_WARN_ACD,,*min_acd,3,true,0,,,,,,,,,,,5,CDRST_WARN_HTTP,10 ` accountActions = ` -vdf,minitsboy;a1;a2,*out,MORE_MINUTES,STANDARD_TRIGGER +vdf,minitsboy,*out,MORE_MINUTES,STANDARD_TRIGGER cgrates.org,12345,*out,TOPUP10_AT,STANDARD_TRIGGERS cgrates.org,remo,*out,TOPUP10_AT, vdf,empty0,*out,TOPUP_SHARED0_AT, @@ -223,6 +223,8 @@ cgrates.org,dan,another,value *out,cgrates.org,call,dan,dan,GLOBAL1,*rating_profile,dan2,20 *any,*any,*any,*any,*any,*any,*rating_profile,rif1,20 *any,*any,*any,*any,*any,*any,*account,dan1,10 +*out,vdf,0,a1,a1,*any,*rating_profile,minu,10 +*out,vdf,0,a1,a1,*any,*account,minu,10 ` ) @@ -1124,7 +1126,7 @@ func TestLoadUsers(t *testing.T) { } func TestLoadAliases(t *testing.T) { - if len(csvr.aliases) != 2 { + if len(csvr.aliases) != 5 { t.Error("Failed to load aliases: ", csvr.aliases) } alias1 := &Alias{ @@ -1140,10 +1142,15 @@ func TestLoadAliases(t *testing.T) { Alias: "dan1", Weight: 10, }, + &AliasValue{ + DestinationId: "GLOBAL1", + Alias: "dan2", + Weight: 20, + }, }, } - if !reflect.DeepEqual(csvr.users[alias1.GetId()], alias1) { + if !reflect.DeepEqual(csvr.aliases[alias1.GetId()], alias1) { t.Errorf("Unexpected alias %+v", csvr.aliases[alias1.GetId()]) } } diff --git a/engine/models.go b/engine/models.go index ebbd73584..03f7f2551 100644 --- a/engine/models.go +++ b/engine/models.go @@ -345,8 +345,8 @@ type TpAlias struct { Category string `index:"2" re:""` Account string `index:"3" re:""` Subject string `index:"4" re:""` - Group string `index:"5" re:""` - DestinationId string `index:"6" re:""` + DestinationId string `index:"5" re:""` + Group string `index:"6" re:""` Alias string `index:"7" re:""` Weight float64 `index:"8" re:""` } diff --git a/engine/storage_csv.go b/engine/storage_csv.go index be9f8d471..831afbb95 100644 --- a/engine/storage_csv.go +++ b/engine/storage_csv.go @@ -25,7 +25,7 @@ func NewFileCSVStorage(sep rune, c.sep = sep c.readerFunc = openFileCSVStorage c.destinationsFn, c.timingsFn, c.ratesFn, c.destinationratesFn, c.destinationratetimingsFn, c.ratingprofilesFn, - c.sharedgroupsFn, c.lcrFn, c.actionsFn, c.actiontimingsFn, c.actiontriggersFn, c.accountactionsFn, c.derivedChargersFn, c.cdrStatsFn, c.usersFn, aliasesFn = destinationsFn, timingsFn, + c.sharedgroupsFn, c.lcrFn, c.actionsFn, c.actiontimingsFn, c.actiontriggersFn, c.accountactionsFn, c.derivedChargersFn, c.cdrStatsFn, c.usersFn, c.aliasesFn = destinationsFn, timingsFn, ratesFn, destinationratesFn, destinationratetimingsFn, ratingprofilesFn, sharedgroupsFn, lcrFn, actionsFn, actiontimingsFn, actiontriggersFn, accountactionsFn, derivedChargersFn, cdrStatsFn, usersFn, aliasesFn return c } diff --git a/engine/storage_map.go b/engine/storage_map.go index 1ea963e76..7b7150488 100644 --- a/engine/storage_map.go +++ b/engine/storage_map.go @@ -501,7 +501,8 @@ func (ms *MapStorage) SetAlias(al *Alias) error { func (ms *MapStorage) GetAlias(key string) (al *Alias, err error) { if values, ok := ms.dict[utils.ALIASES_PREFIX+key]; ok { al = &Alias{Values: make(AliasValues, 0)} - err = ms.ms.Unmarshal(values, al.Values) + err = ms.ms.Unmarshal(values, &al.Values) + al.SetId(key[len(utils.ALIASES_PREFIX):]) } else { return nil, utils.ErrNotFound } @@ -512,8 +513,8 @@ func (ms *MapStorage) GetAliases() (als []*Alias, err error) { for key, value := range ms.dict { if strings.HasPrefix(key, utils.ALIASES_PREFIX) { al := &Alias{Values: make(AliasValues, 0)} - if err = ms.ms.Unmarshal(value, al.Values); err == nil { - al.SetId(key) + if err = ms.ms.Unmarshal(value, &al.Values); err == nil { + al.SetId(key[len(utils.ALIASES_PREFIX):]) als = append(als, al) } } diff --git a/engine/storage_redis.go b/engine/storage_redis.go index bf2cc3e77..fabd8eae9 100644 --- a/engine/storage_redis.go +++ b/engine/storage_redis.go @@ -582,8 +582,8 @@ func (rs *RedisStorage) GetAlias(key string) (al *Alias, err error) { var values []byte if values, err = rs.db.Get(utils.ALIASES_PREFIX + key); err == nil { al = &Alias{Values: make(AliasValues, 0)} - al.SetId(key) - err = rs.ms.Unmarshal(values, al.Values) + al.SetId(key[len(utils.ALIASES_PREFIX):]) + err = rs.ms.Unmarshal(values, &al.Values) } return } @@ -596,7 +596,8 @@ func (rs *RedisStorage) GetAliases() (result []*Alias, err error) { for _, key := range keys { if values, err := rs.db.Get(key); err == nil { al := &Alias{Values: make(AliasValues, 0)} - err = rs.ms.Unmarshal(values, al.Values) + err = rs.ms.Unmarshal(values, &al.Values) + al.SetId(key[len(utils.ALIASES_PREFIX):]) result = append(result, al) } else { return nil, utils.ErrNotFound