first working load distribution lcr

This commit is contained in:
Radu Ioan Fericean
2015-07-31 11:27:38 +03:00
parent 9176f56589
commit d4a440d0ec
2 changed files with 41 additions and 16 deletions

View File

@@ -20,6 +20,7 @@ package engine
import (
"fmt"
"math/rand"
"sort"
"strconv"
"strings"
@@ -37,6 +38,12 @@ const (
LCR_STRATEGY_QOS_THRESHOLD = "*qos_threshold"
LCR_STRATEGY_QOS = "*qos"
LCR_STRATEGY_LOAD = "*load_distribution"
// used for load distribution sorting
RAND_LIMIT = 99
LOW_PRIORITY_LIMIT = 100
MED_PRIORITY_LIMIT = 200
HIGH_PRIORITY_LIMIT = 300
)
// A request for LCR, used in APIer and SM where we need to expose it
@@ -295,6 +302,7 @@ func (lc *LCRCost) Sort() {
sort.Sort(QOSSorter(lc.SupplierCosts))
case LCR_STRATEGY_LOAD:
lc.SortLoadDistribution()
sort.Sort(HighestSupplierCostSorter(lc.SupplierCosts))
}
}
@@ -317,11 +325,11 @@ func (lc *LCRCost) SortLoadDistribution() {
}
}
}
supplierQueues := make(map[string]*StatsQueue)
supplierQueues := make(map[*LCRSupplierCost]*StatsQueue)
for _, supCost := range lc.SupplierCosts {
for _, sq := range supCost.supplierQueues {
if sq.conf.TimeWindow == winnerTimeWindow {
supplierQueues[supCost.Supplier] = sq
supplierQueues[supCost] = sq
break
}
}
@@ -333,13 +341,29 @@ func (lc *LCRCost) SortLoadDistribution() {
// if some have a cdr count not divisible by ponder return them first and all ordered by cdr times, oldest first
// if all have a multiple of ponder return in the order of cdr times, oldest first
// first put them in one of the above categories
for supCost, sq := range supplierQueues {
ponder := lc.GetSupplierPonder(supCost.Supplier)
cdrCount := len(sq.Cdrs)
if cdrCount < ponder {
supCost.Cost = float64(LOW_PRIORITY_LIMIT + rand.Intn(RAND_LIMIT))
continue
}
if cdrCount%ponder == 0 {
supCost.Cost = float64(MED_PRIORITY_LIMIT+rand.Intn(RAND_LIMIT)) + time.Now().Sub(sq.Cdrs[len(sq.Cdrs)-1].SetupTime).Seconds()
continue
} else {
supCost.Cost = float64(HIGH_PRIORITY_LIMIT+rand.Intn(RAND_LIMIT)) + time.Now().Sub(sq.Cdrs[len(sq.Cdrs)-1].SetupTime).Seconds()
continue
}
}
}
// used in load distribution strategy only
// receives a long supplier id and will return the ponder found in strategy params
func (lc *LCRCost) GetSupplierPonder(supplier string) float64 {
func (lc *LCRCost) GetSupplierPonder(supplier string) int {
// parse strategy params
ponders := make(map[string]float64)
ponders := make(map[string]int)
params := strings.Split(lc.Entry.StrategyParams, utils.INFIELD_SEP)
for _, param := range params {
ponderSlice := strings.Split(param, utils.CONCATENATED_KEY_SEP)
@@ -347,7 +371,7 @@ func (lc *LCRCost) GetSupplierPonder(supplier string) float64 {
Logger.Warning(fmt.Sprintf("bad format in load distribution strategy param: %s", lc.Entry.StrategyParams))
continue
}
p, err := strconv.ParseFloat(ponderSlice[1], 64)
p, err := strconv.Atoi(ponderSlice[1])
if err != nil {
Logger.Warning(fmt.Sprintf("bad format in load distribution strategy param: %s", lc.Entry.StrategyParams))
continue

View File

@@ -280,6 +280,7 @@ func TestLCRCostSuppliersString(t *testing.T) {
}
func TestLCRCostSuppliersLoad(t *testing.T) {
setupTime := time.Date(2015, 7, 31, 6, 43, 0, 0, time.UTC)
lcrCost := &LCRCost{
Entry: &LCREntry{DestinationId: utils.ANY, RPCategory: "call", Strategy: LCR_STRATEGY_LOAD, StrategyParams: "ivo12:10;dan12:3;*default:7", Weight: 10.0},
SupplierCosts: []*LCRSupplierCost{
@@ -287,21 +288,21 @@ func TestLCRCostSuppliersLoad(t *testing.T) {
Supplier: "*out:tenant12:call:ivo12",
supplierQueues: []*StatsQueue{
&StatsQueue{
Cdrs: []*QCdr{&QCdr{}, &QCdr{}, &QCdr{}},
Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
conf: &CdrStats{
QueueLength: 0,
TimeWindow: 3 * time.Minute,
},
},
&StatsQueue{
Cdrs: []*QCdr{&QCdr{}, &QCdr{}, &QCdr{}},
Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
conf: &CdrStats{
QueueLength: 0,
TimeWindow: 1 * time.Minute,
},
},
&StatsQueue{
Cdrs: []*QCdr{&QCdr{}, &QCdr{}, &QCdr{}},
Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
conf: &CdrStats{
QueueLength: 0,
TimeWindow: 10 * time.Minute,
@@ -313,21 +314,21 @@ func TestLCRCostSuppliersLoad(t *testing.T) {
Supplier: "*out:tenant12:call:dan12",
supplierQueues: []*StatsQueue{
&StatsQueue{
Cdrs: []*QCdr{&QCdr{}, &QCdr{}, &QCdr{}, &QCdr{}, &QCdr{}},
Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
conf: &CdrStats{
QueueLength: 0,
TimeWindow: 10 * time.Minute,
},
},
&StatsQueue{
Cdrs: []*QCdr{&QCdr{}, &QCdr{}, &QCdr{}, &QCdr{}, &QCdr{}},
Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
conf: &CdrStats{
QueueLength: 0,
TimeWindow: 7 * time.Minute,
},
},
&StatsQueue{
Cdrs: []*QCdr{&QCdr{}, &QCdr{}, &QCdr{}, &QCdr{}, &QCdr{}},
Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
conf: &CdrStats{
QueueLength: 0,
TimeWindow: 7 * time.Minute,
@@ -339,28 +340,28 @@ func TestLCRCostSuppliersLoad(t *testing.T) {
Supplier: "*out:tenant12:call:rif12",
supplierQueues: []*StatsQueue{
&StatsQueue{
Cdrs: []*QCdr{&QCdr{}, &QCdr{}},
Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
conf: &CdrStats{
QueueLength: 0,
TimeWindow: 7 * time.Minute,
},
},
&StatsQueue{
Cdrs: []*QCdr{&QCdr{}, &QCdr{}},
Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
conf: &CdrStats{
QueueLength: 0,
TimeWindow: 7 * time.Minute,
},
},
&StatsQueue{
Cdrs: []*QCdr{&QCdr{}, &QCdr{}},
Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
conf: &CdrStats{
QueueLength: 0,
TimeWindow: 10 * time.Minute,
},
},
&StatsQueue{
Cdrs: []*QCdr{&QCdr{}, &QCdr{}},
Cdrs: []*QCdr{&QCdr{SetupTime: setupTime}, &QCdr{SetupTime: setupTime}},
conf: &CdrStats{
QueueLength: 0,
TimeWindow: 1 * time.Minute,
@@ -374,6 +375,6 @@ func TestLCRCostSuppliersLoad(t *testing.T) {
if lcrCost.SupplierCosts[0].Supplier != "" ||
lcrCost.SupplierCosts[1].Supplier != "" ||
lcrCost.SupplierCosts[2].Supplier != "" {
//t.Error("Error soring on load distribution: ", utils.ToIJSON(lcrCost))
t.Error("Error soring on load distribution: ", utils.ToIJSON(lcrCost))
}
}