From c651aabb32a279f37adf761a50588bbb5cc11b6f Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Fri, 23 Aug 2013 19:54:06 +0300 Subject: [PATCH] killed internal serialization and started using msgpack --- engine/activationperiod_test.go | 97 +++-- engine/calldesc_test.go | 4 + engine/simple_serializer.go | 669 ----------------------------- engine/simple_serializer_test.go | 201 --------- engine/storage_interface.go | 13 - engine/storage_map.go | 2 +- engine/storage_redis.go | 2 +- engine/units_counter_test.go | 19 - engine/userbalance_test.go | 51 +-- sessionmanager/fssessionmanager.go | 4 +- 10 files changed, 78 insertions(+), 984 deletions(-) delete mode 100644 engine/simple_serializer.go delete mode 100644 engine/simple_serializer_test.go diff --git a/engine/activationperiod_test.go b/engine/activationperiod_test.go index 9b17fc467..9c619c9cb 100644 --- a/engine/activationperiod_test.go +++ b/engine/activationperiod_test.go @@ -187,13 +187,6 @@ func BenchmarkActivationPeriodStoreRestoreJson(b *testing.B) { } } -func BenchmarkActivationPeriodRestore(b *testing.B) { - ap := &ActivationPeriod{} - for i := 0; i < b.N; i++ { - ap.Restore("1328106601000000000|;2;1;3,4;14:30:00;15:00:00;0;0;0;0;0") - } -} - func BenchmarkActivationPeriodStoreRestore(b *testing.B) { b.StopTimer() d := time.Date(2012, time.February, 1, 14, 30, 1, 0, time.UTC) @@ -208,32 +201,41 @@ func BenchmarkActivationPeriodStoreRestore(b *testing.B) { ap1 := &ActivationPeriod{} b.StartTimer() for i := 0; i < b.N; i++ { - result, _ := ap.Store() - ap1.Restore(result) + result, _ := marsh.Marshal(ap) + marsh.Unmarshal(result, ap1) } } -func BenchmarkActivationPeriodMarshallerMyStoreRestore(b *testing.B) { - b.StopTimer() - d := time.Date(2012, time.February, 1, 14, 30, 1, 0, time.UTC) - i := &Interval{Months: []time.Month{time.February}, - MonthDays: []int{1}, - WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, - StartTime: "14:30:00", - EndTime: "15:00:00"} - ap := &ActivationPeriod{ActivationTime: d} - ap.AddInterval(i) - - ap1 := &ActivationPeriod{} - b.StartTimer() - ms := new(MyMarshaler) - for i := 0; i < b.N; i++ { - result, _ := ms.Marshal(ap) - ms.Unmarshal(result, ap1) - } -} - -func BenchmarkActivationPeriodMarshallerJSONStoreRestore(b *testing.B) { +func GetUB() *UserBalance { + uc := &UnitsCounter{ + Direction: OUTBOUND, + BalanceId: SMS, + Units: 100, + MinuteBuckets: []*MinuteBucket{&MinuteBucket{Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: ABSOLUTE, DestinationId: "RET"}}, + } + at := &ActionTrigger{ + Id: "some_uuid", + BalanceId: CREDIT, + Direction: OUTBOUND, + ThresholdValue: 100.0, + DestinationId: "NAT", + Weight: 10.0, + ActionsId: "Commando", + } + var zeroTime time.Time + zeroTime = zeroTime.UTC() // for deep equal to find location + ub := &UserBalance{ + Id: "rif", + Type: UB_TYPE_POSTPAID, + BalanceMap: map[string]BalanceChain{SMS + OUTBOUND: BalanceChain{&Balance{Value: 14, ExpirationDate: zeroTime}}, TRAFFIC + OUTBOUND: BalanceChain{&Balance{Value: 1024, ExpirationDate: zeroTime}}}, + MinuteBuckets: []*MinuteBucket{&MinuteBucket{Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: ABSOLUTE, DestinationId: "RET"}}, + UnitCounters: []*UnitsCounter{uc, uc}, + ActionTriggers: ActionTriggerPriotityList{at, at, at}, + } + return ub +} + +func BenchmarkMarshallerJSONStoreRestore(b *testing.B) { b.StopTimer() d := time.Date(2012, time.February, 1, 14, 30, 1, 0, time.UTC) i := &Interval{Months: []time.Month{time.February}, @@ -243,17 +245,21 @@ func BenchmarkActivationPeriodMarshallerJSONStoreRestore(b *testing.B) { EndTime: "15:00:00"} ap := &ActivationPeriod{ActivationTime: d} ap.AddInterval(i) + ub := GetUB() ap1 := ActivationPeriod{} + ub1 := &UserBalance{} b.StartTimer() ms := new(JSONMarshaler) for i := 0; i < b.N; i++ { result, _ := ms.Marshal(ap) ms.Unmarshal(result, ap1) + result, _ = ms.Marshal(ub) + ms.Unmarshal(result, ub1) } } -func BenchmarkActivationPeriodMarshallerBSONStoreRestore(b *testing.B) { +func BenchmarkMarshallerBSONStoreRestore(b *testing.B) { b.StopTimer() d := time.Date(2012, time.February, 1, 14, 30, 1, 0, time.UTC) i := &Interval{Months: []time.Month{time.February}, @@ -263,17 +269,21 @@ func BenchmarkActivationPeriodMarshallerBSONStoreRestore(b *testing.B) { EndTime: "15:00:00"} ap := &ActivationPeriod{ActivationTime: d} ap.AddInterval(i) + ub := GetUB() ap1 := ActivationPeriod{} + ub1 := &UserBalance{} b.StartTimer() ms := new(BSONMarshaler) for i := 0; i < b.N; i++ { result, _ := ms.Marshal(ap) ms.Unmarshal(result, ap1) + result, _ = ms.Marshal(ub) + ms.Unmarshal(result, ub1) } } -func BenchmarkActivationPeriodMarshallerJSONBufStoreRestore(b *testing.B) { +func BenchmarkMarshallerJSONBufStoreRestore(b *testing.B) { b.StopTimer() d := time.Date(2012, time.February, 1, 14, 30, 1, 0, time.UTC) i := &Interval{Months: []time.Month{time.February}, @@ -283,17 +293,21 @@ func BenchmarkActivationPeriodMarshallerJSONBufStoreRestore(b *testing.B) { EndTime: "15:00:00"} ap := &ActivationPeriod{ActivationTime: d} ap.AddInterval(i) + ub := GetUB() ap1 := ActivationPeriod{} + ub1 := &UserBalance{} b.StartTimer() ms := new(JSONBufMarshaler) for i := 0; i < b.N; i++ { result, _ := ms.Marshal(ap) ms.Unmarshal(result, ap1) + result, _ = ms.Marshal(ub) + ms.Unmarshal(result, ub1) } } -func BenchmarkActivationPeriodMarshallerGOBStoreRestore(b *testing.B) { +func BenchmarkMarshallerGOBStoreRestore(b *testing.B) { b.StopTimer() d := time.Date(2012, time.February, 1, 14, 30, 1, 0, time.UTC) i := &Interval{Months: []time.Month{time.February}, @@ -303,17 +317,21 @@ func BenchmarkActivationPeriodMarshallerGOBStoreRestore(b *testing.B) { EndTime: "15:00:00"} ap := &ActivationPeriod{ActivationTime: d} ap.AddInterval(i) + ub := GetUB() ap1 := ActivationPeriod{} + ub1 := &UserBalance{} b.StartTimer() ms := new(GOBMarshaler) for i := 0; i < b.N; i++ { result, _ := ms.Marshal(ap) ms.Unmarshal(result, ap1) + result, _ = ms.Marshal(ub) + ms.Unmarshal(result, ub1) } } -func BenchmarkActivationPeriodMarshallerMsgpackStoreRestore(b *testing.B) { +func BenchmarkMarshallerMsgpackStoreRestore(b *testing.B) { b.StopTimer() d := time.Date(2012, time.February, 1, 14, 30, 1, 0, time.UTC) i := &Interval{Months: []time.Month{time.February}, @@ -323,17 +341,22 @@ func BenchmarkActivationPeriodMarshallerMsgpackStoreRestore(b *testing.B) { EndTime: "15:00:00"} ap := &ActivationPeriod{ActivationTime: d} ap.AddInterval(i) + ub := GetUB() ap1 := ActivationPeriod{} + ub1 := &UserBalance{} b.StartTimer() ms := new(MsgpackMarshaler) for i := 0; i < b.N; i++ { result, _ := ms.Marshal(ap) ms.Unmarshal(result, ap1) + + result, _ = ms.Marshal(ub) + ms.Unmarshal(result, ub1) } } -func BenchmarkActivationPeriodMarshallerBincStoreRestore(b *testing.B) { +func BenchmarkMarshallerBincStoreRestore(b *testing.B) { b.StopTimer() d := time.Date(2012, time.February, 1, 14, 30, 1, 0, time.UTC) i := &Interval{Months: []time.Month{time.February}, @@ -343,12 +366,16 @@ func BenchmarkActivationPeriodMarshallerBincStoreRestore(b *testing.B) { EndTime: "15:00:00"} ap := &ActivationPeriod{ActivationTime: d} ap.AddInterval(i) + ub := GetUB() ap1 := ActivationPeriod{} + ub1 := &UserBalance{} b.StartTimer() ms := NewBincMarshaler() for i := 0; i < b.N; i++ { result, _ := ms.Marshal(ap) ms.Unmarshal(result, ap1) + result, _ = ms.Marshal(ub) + ms.Unmarshal(result, ub1) } } diff --git a/engine/calldesc_test.go b/engine/calldesc_test.go index 877e354cd..cffa333d5 100644 --- a/engine/calldesc_test.go +++ b/engine/calldesc_test.go @@ -25,6 +25,10 @@ import ( "time" ) +var ( + marsh = new(MsgpackMarshaler) +) + func init() { populateDB() historyScribe, _ = history.NewMockScribe() diff --git a/engine/simple_serializer.go b/engine/simple_serializer.go deleted file mode 100644 index ff11ec3a6..000000000 --- a/engine/simple_serializer.go +++ /dev/null @@ -1,669 +0,0 @@ -/* -Rating system designed to be used in VoIP Carriers World -Copyright (C) 2013 ITsysCOM - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ - -package engine - -import ( - "fmt" - "strconv" - "strings" - "time" -) - -type Serializer interface { - Store() (string, error) - Restore(string) error -} - -func notEnoughElements(element, line string) error { - return fmt.Errorf("Too few elements to restore (%v): %v", element, line) -} - -func (ap *ActivationPeriod) Store() (result string, err error) { - result += ap.ActivationTime.Format(time.RFC3339) + "|" - for _, i := range ap.Intervals { - str, err := i.Store() - if err != nil { - return "", err - } - result += str + "|" - } - result = strings.TrimRight(result, "|") - return -} - -func (ap *ActivationPeriod) Restore(input string) error { - elements := strings.Split(input, "|") - var err error - ap.ActivationTime, err = time.Parse(time.RFC3339, elements[0]) - if err != nil { - return err - } - els := elements[1:] - if len(els) > 1 { - els = elements[1 : len(elements)-1] - } - for _, is := range els { - i := &Interval{} - if err := i.Restore(is); err != nil { - return err - } - ap.Intervals = append(ap.Intervals, i) - } - return nil -} - -func (rp *RatingProfile) Store() (result string, err error) { - result += rp.FallbackKey + ">" - for k, aps := range rp.DestinationMap { - result += k + "=" - for _, ap := range aps { - aps, err := ap.Store() - if err != nil { - return result, err - } - result += aps + "<" - } - result = strings.TrimRight(result, "<") - result += ">" - } - result = strings.TrimRight(result, ">") - return -} - -func (rp *RatingProfile) Restore(input string) error { - if rp.DestinationMap == nil { - rp.DestinationMap = make(map[string][]*ActivationPeriod, 1) - } - elements := strings.Split(input, ">") - rp.FallbackKey = elements[0] - for _, kv := range elements[1:] { - pair := strings.SplitN(kv, "=", 2) - apList := strings.Split(pair[1], "<") - var newAps []*ActivationPeriod - for _, aps := range apList { - ap := new(ActivationPeriod) - err := ap.Restore(aps) - if err != nil { - return err - } - newAps = append(newAps, ap) - } - rp.DestinationMap[pair[0]] = newAps - } - return nil -} - -func (a *Action) Store() (result string, err error) { - result += a.Id + "|" - result += a.ActionType + "|" - result += a.BalanceId + "|" - result += a.Direction + "|" - result += a.ExpirationString + "|" - result += a.ExpirationDate.Format(time.RFC3339) + "|" - result += strconv.FormatFloat(a.Units, 'f', -1, 64) + "|" - result += strconv.FormatFloat(a.Weight, 'f', -1, 64) - if a.MinuteBucket != nil { - result += "|" - str, err := a.MinuteBucket.Store() - if err != nil { - return "", err - } - result += str - } - return -} - -func (a *Action) Restore(input string) (err error) { - elements := strings.Split(input, "|") - if len(elements) < 8 { - return notEnoughElements("Action", input) - } - a.Id = elements[0] - a.ActionType = elements[1] - a.BalanceId = elements[2] - a.Direction = elements[3] - a.ExpirationString = elements[4] - if a.ExpirationDate, err = time.Parse(time.RFC3339, elements[5]); err != nil { - return err - } - a.Units, _ = strconv.ParseFloat(elements[6], 64) - a.Weight, _ = strconv.ParseFloat(elements[7], 64) - if len(elements) == 9 { - a.MinuteBucket = &MinuteBucket{} - if err := a.MinuteBucket.Restore(elements[8]); err != nil { - return err - } - } - return nil -} - -func (as Actions) Store() (result string, err error) { - for _, a := range as { - str, err := a.Store() - if err != nil { - return "", err - } - result += str + "~" - } - result = strings.TrimRight(result, "~") - return -} - -func (as *Actions) Restore(input string) error { - for _, a_string := range strings.Split(input, "~") { - if len(a_string) > 0 { - a := &Action{} - if err := a.Restore(a_string); err != nil { - return err - } - *as = append(*as, a) - } - } - return nil -} - -func (at *ActionTiming) Store() (result string, err error) { - result += at.Id + "|" - result += at.Tag + "|" - for _, ubi := range at.UserBalanceIds { - result += ubi + "," - } - result = strings.TrimRight(result, ",") + "|" - if at.Timing != nil { - str, err := at.Timing.Store() - if err != nil { - return "", err - } - result += str + "|" - } else { - result += " |" - } - result += strconv.FormatFloat(at.Weight, 'f', -1, 64) + "|" - result += at.ActionsId - return -} - -func (at *ActionTiming) Restore(input string) error { - elements := strings.Split(input, "|") - at.Id = elements[0] - at.Tag = elements[1] - for _, ubi := range strings.Split(elements[2], ",") { - if strings.TrimSpace(ubi) != "" { - at.UserBalanceIds = append(at.UserBalanceIds, ubi) - } - } - - at.Timing = &Interval{} - if err := at.Timing.Restore(elements[3]); err != nil { - return err - } - at.Weight, _ = strconv.ParseFloat(elements[4], 64) - at.ActionsId = elements[5] - return nil -} - -func (ats ActionTimings) Store() (result string, err error) { - for _, at := range ats { - str, err := at.Store() - if err != nil { - return "", err - } - result += str + "~" - } - result = strings.TrimRight(result, "~") - return -} - -func (ats *ActionTimings) Restore(input string) error { - for _, at_string := range strings.Split(input, "~") { - if len(at_string) > 0 { - at := &ActionTiming{} - if err := at.Restore(at_string); err != nil { - return err - } - *ats = append(*ats, at) - } - } - return nil -} - -func (at *ActionTrigger) Store() (result string, err error) { - result += at.Id + ";" - result += at.BalanceId + ";" - result += at.Direction + ";" - result += at.DestinationId + ";" - result += at.ActionsId + ";" - result += strconv.FormatFloat(at.ThresholdValue, 'f', -1, 64) + ";" - result += at.ThresholdType + ";" - result += strconv.FormatFloat(at.Weight, 'f', -1, 64) + ";" - result += strconv.FormatBool(at.Executed) - return -} - -func (at *ActionTrigger) Restore(input string) error { - elements := strings.Split(input, ";") - if len(elements) != 9 { - return notEnoughElements("ActionTrigger", input) - } - at.Id = elements[0] - at.BalanceId = elements[1] - at.Direction = elements[2] - at.DestinationId = elements[3] - at.ActionsId = elements[4] - at.ThresholdValue, _ = strconv.ParseFloat(elements[5], 64) - at.ThresholdType = elements[6] - at.Weight, _ = strconv.ParseFloat(elements[7], 64) - at.Executed, _ = strconv.ParseBool(elements[8]) - return nil -} - -func (b *Balance) Store() (result string, err error) { - result += b.Id + ")" - result += strconv.FormatFloat(b.Value, 'f', -1, 64) + ")" - result += strconv.FormatFloat(b.Weight, 'f', -1, 64) + ")" - result += b.ExpirationDate.Format(time.RFC3339) - return result, nil -} - -func (b *Balance) Restore(input string) (err error) { - elements := strings.Split(input, ")") - b.Id = elements[0] - b.Value, _ = strconv.ParseFloat(elements[1], 64) - b.Weight, _ = strconv.ParseFloat(elements[2], 64) - b.ExpirationDate, err = time.Parse(time.RFC3339, elements[3]) - return nil -} - -func (bc BalanceChain) Store() (result string, err error) { - for _, b := range bc { - str, err := b.Store() - if err != nil { - return "", err - } - result += str + "^" - } - result = strings.TrimRight(result, "^") - return result, nil -} - -func (bc *BalanceChain) Restore(input string) error { - elements := strings.Split(input, "^") - for _, element := range elements { - b := &Balance{} - err := b.Restore(element) - if err != nil { - return err - } - *bc = append(*bc, b) - } - return nil -} - -func (ub *UserBalance) Store() (result string, err error) { - result += ub.Id + "|" - result += ub.Type + "|" - for k, v := range ub.BalanceMap { - bc, err := v.Store() - if err != nil { - return "", err - } - result += k + "=" + bc + "#" - } - result = strings.TrimRight(result, "#") + "|" - for _, mb := range ub.MinuteBuckets { - str, err := mb.Store() - if err != nil { - return "", err - } - result += str + "#" - } - result = strings.TrimRight(result, "#") + "|" - for _, uc := range ub.UnitCounters { - str, err := uc.Store() - if err != nil { - return "", err - } - result += str + "#" - } - result = strings.TrimRight(result, "#") + "|" - for _, at := range ub.ActionTriggers { - res, err := at.Store() - if err != nil { - return "", err - } - result += res + "#" - } - result = strings.TrimRight(result, "#") - return -} - -func (ub *UserBalance) Restore(input string) error { - elements := strings.Split(input, "|") - if len(elements) < 2 { - return notEnoughElements("UserBalance", input) - } - ub.Id = elements[0] - ub.Type = elements[1] - if ub.BalanceMap == nil { - ub.BalanceMap = make(map[string]BalanceChain, 0) - } - for _, maps := range strings.Split(elements[2], "#") { - kv := strings.Split(maps, "=") - if len(kv) != 2 { - continue - } - bc := BalanceChain{} - if err := (&bc).Restore(kv[1]); err != nil { - return err - } - ub.BalanceMap[kv[0]] = bc - } - for _, mbs := range strings.Split(elements[3], "#") { - if mbs == "" { - continue - } - mb := &MinuteBucket{} - if err := mb.Restore(mbs); err != nil { - return err - } - ub.MinuteBuckets = append(ub.MinuteBuckets, mb) - } - for _, ucs := range strings.Split(elements[4], "#") { - if ucs == "" { - continue - } - uc := &UnitsCounter{} - if err := uc.Restore(ucs); err != nil { - return err - } - ub.UnitCounters = append(ub.UnitCounters, uc) - } - for _, ats := range strings.Split(elements[5], "#") { - if ats == "" { - continue - } - at := &ActionTrigger{} - if err := at.Restore(ats); err != nil { - return err - } - ub.ActionTriggers = append(ub.ActionTriggers, at) - } - return nil -} - -/* -Serializes the unit counter for the storage. Used for key-value storages. -*/ -func (uc *UnitsCounter) Store() (result string, err error) { - result += uc.Direction + "/" - result += uc.BalanceId + "/" - result += strconv.FormatFloat(uc.Units, 'f', -1, 64) + "/" - for _, mb := range uc.MinuteBuckets { - str, err := mb.Store() - if err != nil { - return "", err - } - result += str + "," - } - result = strings.TrimRight(result, ",") - return -} - -/* -De-serializes the unit counter for the storage. Used for key-value storages. -*/ -func (uc *UnitsCounter) Restore(input string) error { - elements := strings.Split(input, "/") - if len(elements) != 4 { - return notEnoughElements("UnitsCounter", input) - } - uc.Direction = elements[0] - uc.BalanceId = elements[1] - uc.Units, _ = strconv.ParseFloat(elements[2], 64) - for _, mbs := range strings.Split(elements[3], ",") { - mb := &MinuteBucket{} - if err := mb.Restore(mbs); err != nil { - return err - } - uc.MinuteBuckets = append(uc.MinuteBuckets, mb) - } - return nil -} - -func (d *Destination) Store() (result string, err error) { - for _, p := range d.Prefixes { - result += p + "," - } - result = strings.TrimRight(result, ",") - return -} - -func (d *Destination) Restore(input string) error { - d.Prefixes = strings.Split(input, ",") - return nil -} - -func (pg PriceGroups) Store() (result string, err error) { - for _, p := range pg { - result += p.GroupIntervalStart.String() + - ":" + strconv.FormatFloat(p.Value, 'f', -1, 64) + - ":" + p.RateIncrement.String() + - ":" + p.RateUnit.String() + - "," - } - result = strings.TrimRight(result, ",") - return -} - -func (pg *PriceGroups) Restore(input string) error { - elements := strings.Split(input, ",") - for _, element := range elements { - priceElements := strings.Split(element, ":") - if len(priceElements) != 4 { - continue - } - ss, err := time.ParseDuration(priceElements[0]) - if err != nil { - return err - } - v, err := strconv.ParseFloat(priceElements[1], 64) - if err != nil { - return err - } - ri, err := time.ParseDuration(priceElements[2]) - if err != nil { - return err - } - ru, err := time.ParseDuration(priceElements[3]) - if err != nil { - return err - } - price := &Price{ - GroupIntervalStart: ss, - Value: v, - RateIncrement: ri, - RateUnit: ru, - } - *pg = append(*pg, price) - } - return nil -} - -func (i *Interval) Store() (result string, err error) { - str, err := i.Years.Store() - if err != nil { - return "", err - } - result += str + ";" - str, err = i.Months.Store() - if err != nil { - return "", err - } - result += str + ";" - str, err = i.MonthDays.Store() - if err != nil { - return "", err - } - result += str + ";" - str, err = i.WeekDays.Store() - if err != nil { - return "", err - } - result += str + ";" - result += i.StartTime + ";" - result += i.EndTime + ";" - result += strconv.FormatFloat(i.Weight, 'f', -1, 64) + ";" - result += strconv.FormatFloat(i.ConnectFee, 'f', -1, 64) + ";" - ps, err := i.Prices.Store() - if err != nil { - return "", err - } - result += ps + ";" - result += i.RoundingMethod + ";" - result += strconv.Itoa(i.RoundingDecimals) - return -} - -func (i *Interval) Restore(input string) error { - is := strings.Split(input, ";") - if len(is) != 11 { - return notEnoughElements("Interval", input) - } - if err := i.Years.Restore(is[0]); err != nil { - return err - } - if err := i.Months.Restore(is[1]); err != nil { - return err - } - if err := i.MonthDays.Restore(is[2]); err != nil { - return err - } - if err := i.WeekDays.Restore(is[3]); err != nil { - return err - } - i.StartTime = is[4] - i.EndTime = is[5] - i.Weight, _ = strconv.ParseFloat(is[6], 64) - i.ConnectFee, _ = strconv.ParseFloat(is[7], 64) - err := (&i.Prices).Restore(is[8]) - if err != nil { - return err - } - i.RoundingMethod = is[9] - i.RoundingDecimals, _ = strconv.Atoi(is[10]) - return nil -} - -func (mb *MinuteBucket) Store() (result string, err error) { - result += strconv.FormatFloat(mb.Seconds, 'f', -1, 64) + ";" - result += strconv.FormatFloat(mb.Weight, 'f', -1, 64) + ";" - result += strconv.FormatFloat(mb.Price, 'f', -1, 64) + ";" - result += mb.PriceType + ";" - result += mb.DestinationId - return -} - -func (mb *MinuteBucket) Restore(input string) error { - input = strings.TrimSpace(input) - if len(input) == 0 { - return nil - } - elements := strings.Split(input, ";") - if len(elements) != 5 { - return notEnoughElements("MinuteBucket", input) - } - mb.Seconds, _ = strconv.ParseFloat(elements[0], 64) - mb.Weight, _ = strconv.ParseFloat(elements[1], 64) - mb.Price, _ = strconv.ParseFloat(elements[2], 64) - mb.PriceType = elements[3] - mb.DestinationId = elements[4] - return nil -} - -func (wds WeekDays) Store() (result string, err error) { - for _, wd := range wds { - result += strconv.Itoa(int(wd)) + "," - } - result = strings.TrimRight(result, ",") - return -} - -func (wds *WeekDays) Restore(input string) error { - for _, wd := range strings.Split(input, ",") { - if wd != "" { - mm, _ := strconv.Atoi(wd) - *wds = append(*wds, time.Weekday(mm)) - } - } - return nil -} - -func (mds MonthDays) Store() (result string, err error) { - for _, md := range mds { - result += strconv.Itoa(int(md)) + "," - } - result = strings.TrimRight(result, ",") - return -} - -func (mds *MonthDays) Restore(input string) error { - for _, md := range strings.Split(input, ",") { - if md != "" { - mm, _ := strconv.Atoi(md) - *mds = append(*mds, mm) - } - } - return nil -} - -func (ms Months) Store() (result string, err error) { - for _, m := range ms { - result += strconv.Itoa(int(m)) + "," - } - result = strings.TrimRight(result, ",") - return -} - -func (ms *Months) Restore(input string) error { - for _, m := range strings.Split(input, ",") { - if m != "" { - mm, _ := strconv.Atoi(m) - *ms = append(*ms, time.Month(mm)) - } - } - return nil -} - -func (yss Years) Store() (result string, err error) { - for _, ys := range yss { - result += strconv.Itoa(int(ys)) + "," - } - result = strings.TrimRight(result, ",") - return -} - -func (yss *Years) Restore(input string) error { - for _, ys := range strings.Split(input, ",") { - if ys != "" { - mm, _ := strconv.Atoi(ys) - *yss = append(*yss, mm) - } - } - return nil -} diff --git a/engine/simple_serializer_test.go b/engine/simple_serializer_test.go deleted file mode 100644 index d8179dfbf..000000000 --- a/engine/simple_serializer_test.go +++ /dev/null @@ -1,201 +0,0 @@ -/* -Rating system designed to be used in VoIP Carriers World -Copyright (C) 2013 ITsysCOM - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ - -package engine - -import ( - "reflect" - "testing" - "time" -) - -func TestSimpleMarshallerApStoreRestore(t *testing.T) { - d := time.Date(2012, time.February, 1, 14, 30, 1, 0, time.UTC) - i := &Interval{ - Months: Months{time.February}, - MonthDays: MonthDays{1}, - WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, - StartTime: "14:30:00", - EndTime: "15:00:00"} - ap := &ActivationPeriod{ActivationTime: d} - ap.AddInterval(i) - result, err := ap.Store() - ap1 := &ActivationPeriod{} - err = ap1.Restore(result) - if err != nil || !reflect.DeepEqual(ap, ap1) { - t.Errorf("Expected %v was %v: %v", ap, ap1, err) - } -} - -func TestSimpleMarshallerApRestoreFromString(t *testing.T) { - s := "2012-02-01T14:30:01Z|;1,2,3,4,5,6,7,8,9,10,11,12;1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31;1,2,3,4,5,6,0;00:00:00;;10;0;0:0.2:1s:60s;1;\n" - ap := &ActivationPeriod{} - err := ap.Restore(s) - if err != nil || len(ap.Intervals) != 1 { - t.Error("Error restoring activation period from string", ap) - } -} - -func TestRpStoreRestore(t *testing.T) { - d := time.Date(2012, time.February, 1, 14, 30, 1, 0, time.UTC) - i := &Interval{ - Months: Months{time.February}, - MonthDays: MonthDays{1}, - WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, - StartTime: "14:30:00", - EndTime: "15:00:00"} - ap := &ActivationPeriod{ActivationTime: d} - ap.AddInterval(i) - rp := &RatingProfile{FallbackKey: "test"} - rp.AddActivationPeriodIfNotPresent("0723", ap) - result, err := rp.Store() - rp1 := &RatingProfile{} - err = rp1.Restore(result) - if err != nil || !reflect.DeepEqual(rp, rp1) { - t.Errorf("Expected %v was %v", rp, rp1) - } -} - -func TestActionTimingStoreRestore(t *testing.T) { - i := &Interval{ - Months: Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December}, - MonthDays: MonthDays{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, - WeekDays: WeekDays{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday}, - StartTime: "18:00:00", - EndTime: "00:00:00", - Weight: 10.0, - ConnectFee: 0.0, - Prices: PriceGroups{&Price{0, 1.0, 1 * time.Second, 60 * time.Second}}, - } - at := &ActionTiming{ - Id: "some uuid", - Tag: "test", - UserBalanceIds: []string{"one", "two", "three"}, - Timing: i, - Weight: 10.0, - ActionsId: "Commando", - } - r, err := at.Store() - o := &ActionTiming{} - err = o.Restore(r) - if err != nil || !reflect.DeepEqual(o, at) { - t.Errorf("Expected %v was %v", at, o) - } -} - -func TestActionTriggerStoreRestore(t *testing.T) { - at := &ActionTrigger{ - Id: "some_uuid", - BalanceId: CREDIT, - Direction: OUTBOUND, - ThresholdValue: 100.0, - ThresholdType: "*max_counter", - DestinationId: "NAT", - Weight: 10.0, - ActionsId: "Commando", - } - r, err := at.Store() - if err != nil || r != "some_uuid;*monetary;*out;NAT;Commando;100;*max_counter;10;false" { - t.Errorf("Error serializing action trigger: %v", string(r)) - } - o := &ActionTrigger{} - err = o.Restore(r) - if err != nil || !reflect.DeepEqual(o, at) { - t.Errorf("Expected %v was %v", at, o) - } -} - -func TestIntervalStoreRestore(t *testing.T) { - i := &Interval{ - Months: Months{time.January, time.February, time.March, time.April, time.May, time.June, time.July, time.August, time.September, time.October, time.November, time.December}, - MonthDays: MonthDays{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, - WeekDays: WeekDays{time.Monday, time.Tuesday, time.Wednesday, time.Thursday, time.Friday}, - StartTime: "18:00:00", - EndTime: "00:00:00", - Weight: 10.0, - ConnectFee: 0.0, - Prices: PriceGroups{&Price{0, 1777.0, 1 * time.Second, 60 * time.Second}}, - } - r, err := i.Store() - o := &Interval{} - err = o.Restore(r) - if err != nil || !reflect.DeepEqual(o, i) { - t.Errorf("Expected %v was %v", i, o) - } -} - -func TestIntervalRestoreFromString(t *testing.T) { - s := ";1,2,3,4,5,6,7,8,9,10,11,12;1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31;1,2,3,4,5,6,0;00:00:00;;10;0;0:0.2:1s:60s;0;" - i := Interval{} - err := i.Restore(s) - if err != nil || !i.Prices.Equal(PriceGroups{&Price{0, 0.2, 1 * time.Second, 60 * time.Second}}) { - t.Errorf("Error restoring inteval period from string %+v", i) - } -} - -func TestMonthYearStoreRestore(t *testing.T) { - y := Years{2010, 2011, 2012} - r, err := y.Store() - if err != nil || r != "2010,2011,2012" { - t.Errorf("Error serializing years: %v", string(r)) - } - o := Years{} - err = o.Restore(r) - if err != nil || !reflect.DeepEqual(o, y) { - t.Errorf("Expected %v was %v", y, o) - } -} - -func TestMonthStoreRestore(t *testing.T) { - m := Months{5, 6, 7, 8} - r, err := m.Store() - if err != nil || r != "5,6,7,8" { - t.Errorf("Error serializing months: %v", string(r)) - } - o := Months{} - err = o.Restore(r) - if err != nil || !reflect.DeepEqual(o, m) { - t.Errorf("Expected %v was %v", m, o) - } -} - -func TestMonthDayStoreRestore(t *testing.T) { - md := MonthDays{24, 25, 26} - r, err := md.Store() - if err != nil || r != "24,25,26" { - t.Errorf("Error serializing month days: %v", string(r)) - } - o := MonthDays{} - err = o.Restore(r) - if err != nil || !reflect.DeepEqual(o, md) { - t.Errorf("Expected %v was %v", md, o) - } -} - -func TestWeekDayStoreRestore(t *testing.T) { - wd := WeekDays{time.Saturday, time.Sunday} - r, err := wd.Store() - if err != nil || r != "6,0" { - t.Errorf("Error serializing week days: %v", string(r)) - } - o := WeekDays{} - err = o.Restore(r) - if err != nil || !reflect.DeepEqual(o, wd) { - t.Errorf("Expected %v was %v", wd, o) - } -} diff --git a/engine/storage_interface.go b/engine/storage_interface.go index 865aa5be1..cdcdd24da 100644 --- a/engine/storage_interface.go +++ b/engine/storage_interface.go @@ -210,16 +210,3 @@ func (gm *GOBMarshaler) Marshal(v interface{}) (data []byte, err error) { func (gm *GOBMarshaler) Unmarshal(data []byte, v interface{}) error { return gob.NewDecoder(bytes.NewBuffer(data)).Decode(v) } - -type MyMarshaler struct{} - -func (mm *MyMarshaler) Marshal(v interface{}) ([]byte, error) { - ser := v.(Serializer) - res, err := ser.Store() - return []byte(res), err -} - -func (mm *MyMarshaler) Unmarshal(data []byte, v interface{}) error { - ser := v.(Serializer) - return ser.Restore(string(data)) -} diff --git a/engine/storage_map.go b/engine/storage_map.go index 1f055862f..40192bbc5 100644 --- a/engine/storage_map.go +++ b/engine/storage_map.go @@ -33,7 +33,7 @@ type MapStorage struct { } func NewMapStorage() (DataStorage, error) { - return &MapStorage{dict: make(map[string][]byte), ms: new(MyMarshaler)}, nil + return &MapStorage{dict: make(map[string][]byte), ms: new(MsgpackMarshaler)}, nil } func (ms *MapStorage) Close() {} diff --git a/engine/storage_redis.go b/engine/storage_redis.go index db131e70d..9f1d107d7 100644 --- a/engine/storage_redis.go +++ b/engine/storage_redis.go @@ -57,7 +57,7 @@ func NewRedisStorage(address string, db int, pass string) (DataStorage, error) { return nil, err } } - return &RedisStorage{db: ndb, dbNb: db, ms: new(MyMarshaler)}, nil + return &RedisStorage{db: ndb, dbNb: db, ms: new(MsgpackMarshaler)}, nil } func (rs *RedisStorage) Close() { diff --git a/engine/units_counter_test.go b/engine/units_counter_test.go index b118d0bbb..0c942d483 100644 --- a/engine/units_counter_test.go +++ b/engine/units_counter_test.go @@ -19,28 +19,9 @@ along with this program. If not, see package engine import ( - "reflect" "testing" ) -func TestUnitsCounterStoreRestore(t *testing.T) { - uc := &UnitsCounter{ - Direction: OUTBOUND, - BalanceId: SMS, - Units: 100, - MinuteBuckets: []*MinuteBucket{&MinuteBucket{Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: ABSOLUTE, DestinationId: "RET"}}, - } - r, err := uc.Store() - if err != nil || r != "*out/*sms/100/0;20;1;;NAT,0;10;10;*absolute;RET" { - t.Errorf("Error serializing units counter: %v", string(r)) - } - o := &UnitsCounter{} - err = o.Restore(r) - if err != nil || !reflect.DeepEqual(o, uc) { - t.Errorf("Expected %v was %v", uc, o) - } -} - func TestUnitsCounterAddMinuteBucket(t *testing.T) { uc := &UnitsCounter{ Direction: OUTBOUND, diff --git a/engine/userbalance_test.go b/engine/userbalance_test.go index 8047df688..80763cee8 100644 --- a/engine/userbalance_test.go +++ b/engine/userbalance_test.go @@ -20,7 +20,6 @@ package engine import ( //"log" - "reflect" "testing" "time" ) @@ -49,12 +48,13 @@ func populateTestActionsForTriggers() { func TestBalanceStoreRestore(t *testing.T) { b := &Balance{Value: 14, Weight: 1, Id: "test", ExpirationDate: time.Date(2013, time.July, 15, 17, 48, 0, 0, time.UTC)} - output, err := b.Store() + marsh := new(MsgpackMarshaler) + output, err := marsh.Marshal(b) if err != nil { t.Error("Error storing balance: ", err) } b1 := &Balance{} - err = b1.Restore(output) + err = marsh.Unmarshal(output, b1) if err != nil { t.Error("Error restoring balance: ", err) } @@ -65,12 +65,13 @@ func TestBalanceStoreRestore(t *testing.T) { func TestBalanceStoreRestoreZero(t *testing.T) { b := &Balance{} - output, err := b.Store() + + output, err := marsh.Marshal(b) if err != nil { t.Error("Error storing balance: ", err) } b1 := &Balance{} - err = b1.Restore(output) + err = marsh.Unmarshal(output, b1) if err != nil { t.Error("Error restoring balance: ", err) } @@ -81,12 +82,12 @@ func TestBalanceStoreRestoreZero(t *testing.T) { func TestBalanceChainStoreRestore(t *testing.T) { bc := BalanceChain{&Balance{Value: 14, ExpirationDate: time.Date(2013, time.July, 15, 17, 48, 0, 0, time.UTC)}, &Balance{Value: 1024}} - output, err := bc.Store() + output, err := marsh.Marshal(bc) if err != nil { t.Error("Error storing balance chain: ", err) } bc1 := BalanceChain{} - err = (&bc1).Restore(output) + err = marsh.Unmarshal(output, &bc1) if err != nil { t.Error("Error restoring balance chain: ", err) } @@ -95,42 +96,6 @@ func TestBalanceChainStoreRestore(t *testing.T) { } } -func TestUserBalanceStoreRestore(t *testing.T) { - uc := &UnitsCounter{ - Direction: OUTBOUND, - BalanceId: SMS, - Units: 100, - MinuteBuckets: []*MinuteBucket{&MinuteBucket{Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: ABSOLUTE, DestinationId: "RET"}}, - } - at := &ActionTrigger{ - Id: "some_uuid", - BalanceId: CREDIT, - Direction: OUTBOUND, - ThresholdValue: 100.0, - DestinationId: "NAT", - Weight: 10.0, - ActionsId: "Commando", - } - var zeroTime time.Time - zeroTime = zeroTime.UTC() // for deep equal to find location - ub := &UserBalance{ - Id: "rif", - Type: UB_TYPE_POSTPAID, - BalanceMap: map[string]BalanceChain{SMS + OUTBOUND: BalanceChain{&Balance{Value: 14, ExpirationDate: zeroTime}}, TRAFFIC + OUTBOUND: BalanceChain{&Balance{Value: 1024, ExpirationDate: zeroTime}}}, - MinuteBuckets: []*MinuteBucket{&MinuteBucket{Weight: 20, Price: 1, DestinationId: "NAT"}, &MinuteBucket{Weight: 10, Price: 10, PriceType: ABSOLUTE, DestinationId: "RET"}}, - UnitCounters: []*UnitsCounter{uc, uc}, - ActionTriggers: ActionTriggerPriotityList{at, at, at}, - } - - var err error - r, err := ub.Store() - o := &UserBalance{} - err = o.Restore(r) - if err != nil || !reflect.DeepEqual(ub, o) { - t.Errorf("Expected [%v] was [%v] , err: %v", ub, o, err) - } -} - func TestUserBalanceStorageStoreRestore(t *testing.T) { b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.01, DestinationId: "NAT"} b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"} diff --git a/sessionmanager/fssessionmanager.go b/sessionmanager/fssessionmanager.go index 918c98624..1a439e9a2 100644 --- a/sessionmanager/fssessionmanager.go +++ b/sessionmanager/fssessionmanager.go @@ -103,11 +103,11 @@ func (sm *FSSessionManager) DisconnectSession(s *Session, notify string) { engine.Logger.Debug(fmt.Sprintf("Session: %+v", s.uuid)) err := fsock.FS.SendApiCmd(fmt.Sprintf("uuid_setvar %s cgr_notify %s\n\n", s.uuid, notify)) if err != nil { - engine.Logger.Err("could not send disconect api notification to freeswitch") + engine.Logger.Err(fmt.Sprintf("could not send disconect api notification to freeswitch: %v", err)) } err = fsock.FS.SendMsgCmd(s.uuid, map[string]string{"call-command": "hangup", "hangup-cause": "MANAGER_REQUEST"}) // without + sign if err != nil { - engine.Logger.Err("could not send disconect msg to freeswitch") + engine.Logger.Err(fmt.Sprintf("could not send disconect msg to freeswitch: %v", err)) } return }