From 12540225b1cc5733e4455a507abb4de4c7be9160 Mon Sep 17 00:00:00 2001 From: Radu Ioan Fericean Date: Thu, 1 Mar 2012 00:06:34 +0200 Subject: [PATCH] gob is creating extra problems --- timespans/activationperiod_test.go | 22 +++++- timespans/calldesc.go | 2 +- timespans/calldesc_test.go | 2 +- timespans/destinations.go | 20 ----- timespans/destinations_test.go | 10 --- timespans/kyoto_storage.go | 113 +++++++++++++++++++---------- timespans/minute_buckets.go | 24 ------ timespans/minute_buckets_test.go | 26 +++++++ timespans/redis_storage.go | 101 +++++++++++++++++--------- timespans/tariff_plans.go | 86 ---------------------- timespans/tariff_plans_test.go | 19 ----- timespans/test.kch | Bin 6300016 -> 6301376 bytes timespans/userbudget.go | 49 +------------ timespans/userbudget_test.go | 13 ---- 14 files changed, 194 insertions(+), 293 deletions(-) diff --git a/timespans/activationperiod_test.go b/timespans/activationperiod_test.go index 3ada91f9b..8f5b62244 100644 --- a/timespans/activationperiod_test.go +++ b/timespans/activationperiod_test.go @@ -47,7 +47,7 @@ func TestApRestoreRedis(t *testing.T) { } func TestApStoreRestore(t *testing.T) { - getter, _ := NewRedisStorage("tcp:127.0.0.1:6379", 10) + getter, _ := NewKyotoStorage("test.kch") defer getter.Close() d := time.Date(2012, time.February, 1, 14, 30, 1, 0, time.UTC) i := &Interval{Month: time.February, @@ -68,3 +68,23 @@ func TestApStoreRestore(t *testing.T) { } /**************************** Benchmarks *************************************/ + +func BenchmarkActivationPeriodStoreRestore(b *testing.B) { + b.StopTimer() + getter, _ := NewKyotoStorage("test.kch") + defer getter.Close() + d := time.Date(2012, time.February, 1, 14, 30, 1, 0, time.UTC) + i := &Interval{Month: time.February, + MonthDay: 1, + WeekDays: []time.Weekday{time.Wednesday, time.Thursday}, + StartTime: "14:30:00", + EndTime: "15:00:00"} + ap := &ActivationPeriod{ActivationTime: d} + ap.AddInterval(i) + + b.StartTimer() + for i := 0; i < b.N; i++ { + getter.SetActivationPeriods("storerestore", []*ActivationPeriod{ap}) + getter.GetActivationPeriods("storerestore") + } +} diff --git a/timespans/calldesc.go b/timespans/calldesc.go index 888081061..05a5291bb 100644 --- a/timespans/calldesc.go +++ b/timespans/calldesc.go @@ -269,7 +269,7 @@ func (cd *CallDescriptor) GetMaxSessionTime() (seconds float64, err error) { cost := 0.0 for i, ts := range timespans { - if ts.MinuteInfo == nil && i == 0 { + if i == 0 && ts.MinuteInfo == nil && ts.Interval != nil { cost += ts.Interval.ConnectFee } cost += ts.GetCost(cd) diff --git a/timespans/calldesc_test.go b/timespans/calldesc_test.go index 736203666..c50215bd8 100644 --- a/timespans/calldesc_test.go +++ b/timespans/calldesc_test.go @@ -209,7 +209,7 @@ func TestMaxSessionTimeNoUserBudget(t *testing.T) { defer getter.Close() cd := &CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0723", storageGetter: getter, Amount: 1000} result, err := cd.GetMaxSessionTime() - if result != 1000 || err != nil { + if result != 1000 || err == nil { t.Errorf("Expected %v was %v", 1000, result) } } diff --git a/timespans/destinations.go b/timespans/destinations.go index 15a660ae3..b0f4ea2e5 100644 --- a/timespans/destinations.go +++ b/timespans/destinations.go @@ -17,11 +17,6 @@ along with this program. If not, see */ package timespans -import ( - //"log" - "strings" -) - /* Structure that gathers multiple destination prefixes under a common id. */ @@ -30,21 +25,6 @@ type Destination struct { Prefixes []string } -/* -Serializes the destination for the storage. Used for key-value storages. -*/ -func (d *Destination) store() (result string) { - for _, p := range d.Prefixes { - result += p + "," - } - result = strings.TrimRight(result, ",") - return -} - -func (d *Destination) restore(input string) { - d.Prefixes = strings.Split(input, ",") -} - /* De-serializes the destination for the storage. Used for key-value storages. */ diff --git a/timespans/destinations_test.go b/timespans/destinations_test.go index 6e4b4d2fc..188e0556b 100644 --- a/timespans/destinations_test.go +++ b/timespans/destinations_test.go @@ -21,16 +21,6 @@ import ( "testing" ) -func TestDestinationStoreRestore(t *testing.T) { - nationale = &Destination{Id: "nat", Prefixes: []string{"0257", "0256", "0723"}} - s := nationale.store() - d1 := &Destination{Id: "nat"} - d1.restore(s) - if d1.store() != s { - t.Errorf("Expected %q was %q", s, d1.store()) - } -} - func TestDestinationKyotoStore(t *testing.T) { getter, _ := NewKyotoStorage("test.kch") defer getter.Close() diff --git a/timespans/kyoto_storage.go b/timespans/kyoto_storage.go index 1c7b42205..05a433bf8 100644 --- a/timespans/kyoto_storage.go +++ b/timespans/kyoto_storage.go @@ -1,11 +1,11 @@ /* -Rating system designed to be used in VoIP Carriers World +Rating system designed to be used in VoIP Carrieks World Copyright (C) 2012 Radu Ioan Fericean 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. +the Free Software Foundation, either veksion 3 of the License, or +(at your option) any later veksion. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -21,25 +21,38 @@ import ( "bitbucket.org/ww/cabinet" "bytes" "encoding/gob" - //"github.com/fsouza/gokabinet/kc" - // "log" + //"log" "sync" ) type KyotoStorage struct { //db *kc.DB - db *cabinet.KCDB - buf bytes.Buffer - dec *gob.Decoder - mux sync.Mutex // we need norma lock because we reset the buf variable + db *cabinet.KCDB + buf bytes.Buffer + decAP *gob.Decoder + encAP *gob.Encoder + decDest *gob.Decoder + encDest *gob.Encoder + decTP *gob.Decoder + encTP *gob.Encoder + decUB *gob.Decoder + encUB *gob.Encoder + mux sync.Mutex // we need norma lock because we reset the buf variable } func NewKyotoStorage(filaName string) (*KyotoStorage, error) { - //ndb, err := kc.Open(filaName, kc.WRITE) ndb := cabinet.New() err := ndb.Open(filaName, cabinet.KCOWRITER|cabinet.KCOCREATE) ks := &KyotoStorage{db: ndb} - ks.dec = gob.NewDecoder(&ks.buf) + + ks.decAP = gob.NewDecoder(&ks.buf) + ks.encAP = gob.NewEncoder(&ks.buf) + ks.decDest = gob.NewDecoder(&ks.buf) + ks.encDest = gob.NewEncoder(&ks.buf) + ks.decTP = gob.NewDecoder(&ks.buf) + ks.encTP = gob.NewEncoder(&ks.buf) + ks.decUB = gob.NewDecoder(&ks.buf) + ks.encUB = gob.NewEncoder(&ks.buf) return ks, err } @@ -51,10 +64,9 @@ func (ks *KyotoStorage) SetActivationPeriods(key string, aps []*ActivationPeriod ks.mux.Lock() defer ks.mux.Unlock() - var writeBuf bytes.Buffer - encoder := gob.NewEncoder(&writeBuf) - encoder.Encode(aps) - return ks.db.Set([]byte(key), writeBuf.Bytes()) + ks.buf.Reset() + ks.encAP.Encode(aps) + return ks.db.Set([]byte(key), ks.buf.Bytes()) } func (ks *KyotoStorage) GetActivationPeriods(key string) (aps []*ActivationPeriod, err error) { @@ -65,42 +77,69 @@ func (ks *KyotoStorage) GetActivationPeriods(key string) (aps []*ActivationPerio ks.buf.Reset() ks.buf.Write(values) - ks.dec.Decode(&aps) - return -} - -func (ks *KyotoStorage) GetDestination(key string) (dest *Destination, err error) { - if values, err := ks.db.Get([]byte(key)); err == nil { - dest = &Destination{Id: key} - dest.restore(string(values)) - } + ks.decAP.Decode(&aps) return } func (ks *KyotoStorage) SetDestination(dest *Destination) error { - return ks.db.Set([]byte(dest.Id), []byte(dest.store())) + ks.mux.Lock() + defer ks.mux.Unlock() + + ks.buf.Reset() + ks.encDest.Encode(dest) + return ks.db.Set([]byte(dest.Id), ks.buf.Bytes()) } -func (ks *KyotoStorage) GetTariffPlan(key string) (tp *TariffPlan, err error) { - if values, err := ks.db.Get([]byte(key)); err == nil { - tp = &TariffPlan{Id: key} - tp.restore(string(values)) - } +func (ks *KyotoStorage) GetDestination(key string) (dest *Destination, err error) { + ks.mux.Lock() + defer ks.mux.Unlock() + + values, err := ks.db.Get([]byte(key)) + + ks.buf.Reset() + ks.buf.Write(values) + ks.decDest.Decode(&dest) return } func (ks *KyotoStorage) SetTariffPlan(tp *TariffPlan) error { - return ks.db.Set([]byte(tp.Id), []byte(tp.store())) + ks.mux.Lock() + defer ks.mux.Unlock() + + ks.buf.Reset() + ks.encTP.Encode(tp) + return ks.db.Set([]byte(tp.Id), ks.buf.Bytes()) } -func (ks *KyotoStorage) GetUserBudget(key string) (ub *UserBudget, err error) { - if values, err := ks.db.Get([]byte(key)); err == nil { - ub = &UserBudget{Id: key} - ub.restore(string(values)) - } +func (ks *KyotoStorage) GetTariffPlan(key string) (tp *TariffPlan, err error) { + ks.mux.Lock() + defer ks.mux.Unlock() + + values, err := ks.db.Get([]byte(key)) + + ks.buf.Reset() + ks.buf.Write(values) + ks.decTP.Decode(&tp) return } func (ks *KyotoStorage) SetUserBudget(ub *UserBudget) error { - return ks.db.Set([]byte(ub.Id), []byte(ub.store())) + ks.mux.Lock() + defer ks.mux.Unlock() + + ks.buf.Reset() + ks.encUB.Encode(ub) + return ks.db.Set([]byte(ub.Id), ks.buf.Bytes()) +} + +func (ks *KyotoStorage) GetUserBudget(key string) (ub *UserBudget, err error) { + ks.mux.Lock() + defer ks.mux.Unlock() + + values, err := ks.db.Get([]byte(key)) + + ks.buf.Reset() + ks.buf.Write(values) + ks.decUB.Decode(&ub) + return } diff --git a/timespans/minute_buckets.go b/timespans/minute_buckets.go index 908c7fcc1..c24821e2f 100644 --- a/timespans/minute_buckets.go +++ b/timespans/minute_buckets.go @@ -20,8 +20,6 @@ package timespans import ( // "log" "math" - "strconv" - "strings" ) type MinuteBucket struct { @@ -33,28 +31,6 @@ type MinuteBucket struct { precision int } -/* -Serializes the minute bucket for the storage. Used for key-value storages. -*/ -func (mb *MinuteBucket) store() (result string) { - result += strconv.Itoa(int(mb.Seconds)) + "|" - result += strconv.Itoa(int(mb.Priority)) + "|" - result += strconv.FormatFloat(mb.Price, 'f', -1, 64) + "|" - result += mb.DestinationId - return -} - -/* -De-serializes the minute bucket for the storage. Used for key-value storages. -*/ -func (mb *MinuteBucket) restore(input string) { - elements := strings.Split(input, "|") - mb.Seconds, _ = strconv.ParseFloat(elements[0], 64) - mb.Priority, _ = strconv.Atoi(elements[1]) - mb.Price, _ = strconv.ParseFloat(elements[2], 64) - mb.DestinationId = elements[3] -} - /* Returns the destination loading it from the storage if necessary. */ diff --git a/timespans/minute_buckets_test.go b/timespans/minute_buckets_test.go index 4ff934f03..ee4312df8 100644 --- a/timespans/minute_buckets_test.go +++ b/timespans/minute_buckets_test.go @@ -30,3 +30,29 @@ func TestGetDestination(t *testing.T) { t.Error("Got wrong destination: ", d) } } + +func TestMultipleGetDestination(t *testing.T) { + getter, _ := NewRedisStorage("tcp:127.0.0.1:6379", 10) + defer getter.Close() + mb := &MinuteBucket{DestinationId: "nationale"} + d := mb.getDestination(getter) + d = mb.getDestination(getter) + d = mb.getDestination(getter) + if d.Id != "nationale" || len(d.Prefixes) != 4 { + t.Error("Got wrong destination: ", d) + } + /*mb = &MinuteBucket{DestinationId: "retea"} + d = mb.getDestination(getter) + d = mb.getDestination(getter) + d = mb.getDestination(getter) + if d.Id != "retea" || len(d.Prefixes) != 2 { + t.Error("Got wrong destination: ", d) + } + mb = &MinuteBucket{DestinationId: "mobil"} + d = mb.getDestination(getter) + d = mb.getDestination(getter) + d = mb.getDestination(getter) + if d.Id != "mobil" || len(d.Prefixes) != 2 { + t.Error("Got wrong destination: ", d) + }*/ +} diff --git a/timespans/redis_storage.go b/timespans/redis_storage.go index a7520decb..511be6b9f 100644 --- a/timespans/redis_storage.go +++ b/timespans/redis_storage.go @@ -21,23 +21,29 @@ import ( "bytes" "encoding/gob" "github.com/simonz05/godis" - // "log" + "log" "sync" ) type RedisStorage struct { - dbNb int - db *godis.Client - buf bytes.Buffer - dec *gob.Decoder - mux sync.Mutex + dbNb int + db *godis.Client + buf bytes.Buffer + decAP *gob.Decoder + decDest *gob.Decoder + decTP *gob.Decoder + decUB *gob.Decoder + mux sync.Mutex } func NewRedisStorage(address string, db int) (*RedisStorage, error) { ndb := godis.New(address, db, "") rs := &RedisStorage{db: ndb, dbNb: db} - rs.dec = gob.NewDecoder(&rs.buf) + rs.decAP = gob.NewDecoder(&rs.buf) + rs.decDest = gob.NewDecoder(&rs.buf) + rs.decTP = gob.NewDecoder(&rs.buf) + rs.decUB = gob.NewDecoder(&rs.buf) return rs, nil } @@ -49,6 +55,7 @@ func (rs *RedisStorage) SetActivationPeriods(key string, aps []*ActivationPeriod //.db.Select(rs.dbNb) rs.mux.Lock() defer rs.mux.Unlock() + var writeBuf bytes.Buffer encoder := gob.NewEncoder(&writeBuf) encoder.Encode(aps) @@ -64,48 +71,76 @@ func (rs *RedisStorage) GetActivationPeriods(key string) (aps []*ActivationPerio rs.buf.Reset() rs.buf.Write(elem.Bytes()) - rs.dec.Decode(&aps) - return -} - -func (rs *RedisStorage) GetDestination(key string) (dest *Destination, err error) { - //rs.db.Select(rs.dbNb + 1) - if values, err := rs.db.Get(key); err == nil { - dest = &Destination{Id: key} - dest.restore(values.String()) - } + rs.decAP.Decode(&aps) return } func (rs *RedisStorage) SetDestination(dest *Destination) error { - //rs.db.Select(rs.dbNb + 1) - return rs.db.Set(dest.Id, dest.store()) + //rs.db.Select(rs.dbNb + 1) + rs.mux.Lock() + defer rs.mux.Unlock() + + var writeBuf bytes.Buffer + encoder := gob.NewEncoder(&writeBuf) + encoder.Encode(dest) + return rs.db.Set(dest.Id, writeBuf.Bytes()) } -func (rs *RedisStorage) GetTariffPlan(key string) (tp *TariffPlan, err error) { - //rs.db.Select(rs.dbNb + 2) - if values, err := rs.db.Get(key); err == nil { - tp = &TariffPlan{Id: key} - tp.restore(values.String()) - } +func (rs *RedisStorage) GetDestination(key string) (dest *Destination, err error) { + //rs.db.Select(rs.dbNb + 1) + rs.mux.Lock() + defer rs.mux.Unlock() + + elem, err := rs.db.Get(key) + rs.buf.Reset() + rs.buf.Write(elem.Bytes()) + err = rs.decDest.Decode(&dest) + log.Print(err) return } func (rs *RedisStorage) SetTariffPlan(tp *TariffPlan) error { //rs.db.Select(rs.dbNb + 2) - return rs.db.Set(tp.Id, tp.store()) + rs.mux.Lock() + defer rs.mux.Unlock() + + var writeBuf bytes.Buffer + encoder := gob.NewEncoder(&writeBuf) + encoder.Encode(tp) + return rs.db.Set(tp.Id, writeBuf.Bytes()) } -func (rs *RedisStorage) GetUserBudget(key string) (ub *UserBudget, err error) { - //rs.db.Select(rs.dbNb + 3) - if values, err := rs.db.Get(key); err == nil { - ub = &UserBudget{Id: key} - ub.restore(values.String()) - } +func (rs *RedisStorage) GetTariffPlan(key string) (tp *TariffPlan, err error) { + //rs.db.Select(rs.dbNb + 2) + rs.mux.Lock() + defer rs.mux.Unlock() + + elem, err := rs.db.Get(key) + rs.buf.Reset() + rs.buf.Write(elem.Bytes()) + rs.decTP.Decode(&tp) return } func (rs *RedisStorage) SetUserBudget(ub *UserBudget) error { //rs.db.Select(rs.dbNb + 3) - return rs.db.Set(ub.Id, ub.store()) + rs.mux.Lock() + defer rs.mux.Unlock() + + var writeBuf bytes.Buffer + encoder := gob.NewEncoder(&writeBuf) + encoder.Encode(ub) + return rs.db.Set(ub.Id, writeBuf.Bytes()) +} + +func (rs *RedisStorage) GetUserBudget(key string) (ub *UserBudget, err error) { + //rs.db.Select(rs.dbNb + 3) + rs.mux.Lock() + defer rs.mux.Unlock() + + elem, err := rs.db.Get(key) + rs.buf.Reset() + rs.buf.Write(elem.Bytes()) + rs.decUB.Decode(&ub) + return } diff --git a/timespans/tariff_plans.go b/timespans/tariff_plans.go index b69a287da..3b2d8115b 100644 --- a/timespans/tariff_plans.go +++ b/timespans/tariff_plans.go @@ -19,8 +19,6 @@ package timespans import ( // "log" - "strconv" - "strings" ) /* @@ -45,62 +43,6 @@ type VolumeDiscount struct { Discount float64 // procentage } -/* -Serializes the tariff plan for the storage. Used for key-value storages. -*/ -func (tp *TariffPlan) store() (result string) { - result += strconv.FormatFloat(tp.SmsCredit, 'f', -1, 64) + ";" - result += strconv.FormatFloat(tp.Traffic, 'f', -1, 64) + ";" - result += strconv.FormatFloat(tp.ReceivedCallSecondsLimit, 'f', -1, 64) + ";" - if tp.RecivedCallBonus == nil { - tp.RecivedCallBonus = &RecivedCallBonus{} - } - result += tp.RecivedCallBonus.store() + ";" - for i, mb := range tp.MinuteBuckets { - if i > 0 { - result += "," - } - result += mb.store() - } - if tp.VolumeDiscountThresholds != nil { - result += ";" - } - for i, vd := range tp.VolumeDiscountThresholds { - if i > 0 { - result += "," - } - result += strconv.FormatFloat(vd.Volume, 'f', -1, 64) + "|" + strconv.FormatFloat(vd.Discount, 'f', -1, 64) - } - result = strings.TrimRight(result, ";") - return -} - -/* -De-serializes the tariff plan for the storage. Used for key-value storages. -*/ -func (tp *TariffPlan) restore(input string) { - elements := strings.Split(input, ";") - tp.SmsCredit, _ = strconv.ParseFloat(elements[0], 64) - tp.Traffic, _ = strconv.ParseFloat(elements[1], 64) - tp.ReceivedCallSecondsLimit, _ = strconv.ParseFloat(elements[2], 64) - tp.RecivedCallBonus = &RecivedCallBonus{} - tp.RecivedCallBonus.restore(elements[3]) - for _, mbs := range strings.Split(elements[4], ",") { - mb := &MinuteBucket{} - mb.restore(mbs) - tp.MinuteBuckets = append(tp.MinuteBuckets, mb) - } - if len(elements) > 5 { - for _, vdss := range strings.Split(elements[5], ",") { - vd := &VolumeDiscount{} - vds := strings.Split(vdss, "|") - vd.Volume, _ = strconv.ParseFloat(vds[0], 64) - vd.Discount, _ = strconv.ParseFloat(vds[1], 64) - tp.VolumeDiscountThresholds = append(tp.VolumeDiscountThresholds, vd) - } - } -} - /* Structure to be filled for each tariff plan with the bonus value for received calls minutes. */ @@ -110,31 +52,3 @@ type RecivedCallBonus struct { Traffic float64 MinuteBucket *MinuteBucket } - -/* -Serializes the tariff plan for the storage. Used for key-value storages. -*/ -func (rcb *RecivedCallBonus) store() (result string) { - result += strconv.FormatFloat(rcb.Credit, 'f', -1, 64) + "," - result += strconv.FormatFloat(rcb.SmsCredit, 'f', -1, 64) + "," - result += strconv.FormatFloat(rcb.Traffic, 'f', -1, 64) - if rcb.MinuteBucket != nil { - result += "," - result += rcb.MinuteBucket.store() - } - return -} - -/* -De-serializes the tariff plan for the storage. Used for key-value storages. -*/ -func (rcb *RecivedCallBonus) restore(input string) { - elements := strings.Split(input, ",") - rcb.Credit, _ = strconv.ParseFloat(elements[0], 64) - rcb.SmsCredit, _ = strconv.ParseFloat(elements[1], 64) - rcb.Traffic, _ = strconv.ParseFloat(elements[2], 64) - if len(elements) > 3 { - rcb.MinuteBucket = &MinuteBucket{} - rcb.MinuteBucket.restore(elements[3]) - } -} diff --git a/timespans/tariff_plans_test.go b/timespans/tariff_plans_test.go index bb2ad3dcb..ca7951501 100644 --- a/timespans/tariff_plans_test.go +++ b/timespans/tariff_plans_test.go @@ -21,25 +21,6 @@ import ( "testing" ) -func TestTariffPlanStoreRestore(t *testing.T) { - b1 := &MinuteBucket{Seconds: 10, Priority: 10, Price: 0.01, DestinationId: "nationale"} - b2 := &MinuteBucket{Seconds: 100, Priority: 20, Price: 0.0, DestinationId: "retea"} - rcb := &RecivedCallBonus{Credit: 100} - vd := &VolumeDiscount{100, 10} - seara := &TariffPlan{Id: "seara_voo", - SmsCredit: 100, - ReceivedCallSecondsLimit: 0, - RecivedCallBonus: rcb, - MinuteBuckets: []*MinuteBucket{b1, b2}, - VolumeDiscountThresholds: []*VolumeDiscount{vd}} - s := seara.store() - tp1 := &TariffPlan{Id: "seara_voo"} - tp1.restore(s) - if tp1.store() != s { - t.Errorf("Expected %q was %q", s, tp1.store()) - } -} - func TestTariffPlanKyotoStore(t *testing.T) { getter, _ := NewKyotoStorage("test.kch") defer getter.Close() diff --git a/timespans/test.kch b/timespans/test.kch index b8ae5165818304f01b5a81280af4d833aad19766..732fa2157b3e1907b19deb529f45641405643d0e 100644 GIT binary patch delta 3191 zcmc&#O>7%Q6rSf@yLND)h4d%1sRRln>LId|xS^>aTPGw9ZAjHPg%E{!V~>+nY;U!@ zj@lx$O_VB!lBQ`Xp_CTo#tD%_mMlk+>mlfFgS15)W_I-q>5aC2l2Z`P+T7 z^XAQ)neTn`_x(%4y`L`$*BX7h2>(T2zc&-S9E7!?YkWy0eqq6G-nt_A#hBe1Uz(BD zBpCfl@C#!z!L=a#vVi6v#r{=k@!R0cI=yPVe5w7;#ro*UzIk0N3UNW?^S7}wdNnXaqzj~U|eWu{;1Z8kPyca zVMG_A8}T-x2hoc-f#^fLgE)yeh3H4Tn?0%xykWq+9d-UqTwJ5wI`;8=`$_~cggA?M z5Ai-?81X^2eP!h3pWvYFT{xQW>$B(gM_1q=SO;5p_-De?@kEEFBsu~uq4wpT1JV2S z8|yBI&#PN5?Jcd#R}MuRURigSdhE75Qc5~wsCuR&P;h(ABxGGIb@WZ8WkXTZa*{T) z1p(l>ZmJtf{v)uf1YF?ii-Vtl_q0Y6%6X~-yM`h5vPBnwcVtvIG$lR3KcW|DU{}Gn z6%#}eS8;?t+C|L5Y{h3=fNWp@XCm%>8a1fA7l*qo3tW5v_it&d=$}%@m89iwSw(+4 zzGFwkeVQE4nA~6F7C;RTA7~4;wj8nIKb+9qA)U&a%dB$ODp_n)CLs!Y>(mz+!v(wLf#oBAmwmG|6*y>@3<9#b=EBQmK`eNs)vvG+^d#vyhC)2kd!1Wz$F zo~T)DmS*ZNofX(;7qN5>ci|ddLD2%I=6r?9M~6}Y_|k(p@l5<3!9nv1T}!&CE&9O{18PdGh~nR1WG9IQaQ^lYP@)c>eT3#FAO9ileAw=8FGcF*x~O&y=2nuIfW z&_>hqWU-xR?Vs({4OOEk3;dP6SRdUDW{7=40AAoJJpbc&T?)PlV*psdsOTOqc!O;n zt$~g}0Id+d@L!;^LpOyeih1={gIVcrs6+7;FdPVl3&FY?P=yQn>)}b-Ki{0!D%!DW zRjpow&BuuF|DnNVQPRsqxN?P+N$pcZorz-iEVb^~cJAaos6=jSp$6s&>YV%xAdsL~&}i6d$hg&zDQO}L0}t~P7ytIx%@>9MaVQXn0dY7GM*wjo5Jzn{Ul=WQf{`0pA24c;$ZoHYNLa`y1CCc1 z!P6XEmXc;wl$mB_U}S2(eX2x)AmemXsf0taXJBf;G*6Q;T%oy(8(ttL7BWODxIE&r8fn1=??>19F58NDGiKF?a`5dWH#E zJu7EXYDsD$RE3erI}G{U{G`krBok2ev($4HC8m^u^}HIBX%t8em8_1{W^bXbKY-UMC`Pr#Okbr@hMuK6W zsAOkgs7JVwnGYD0kO&7yJupr{5e@_(g$TfD0d{hHS$;k+P$7OHF;ZaWsxT-a%w=HZ W&o9YHEi!}$kTEb=tlv#ER0aU|3tm3} diff --git a/timespans/userbudget.go b/timespans/userbudget.go index 4de2a75e6..3d9d2a4c5 100644 --- a/timespans/userbudget.go +++ b/timespans/userbudget.go @@ -20,8 +20,6 @@ package timespans import ( // "log" "sort" - "strconv" - "strings" "sync" ) @@ -70,55 +68,11 @@ func (bs bucketsorter) Less(j, i int) bool { bs[i].Price > bs[j].Price } -/* -Serializes the user budget for the storage. Used for key-value storages. -*/ -func (ub *UserBudget) store() (result string) { - result += strconv.FormatFloat(ub.Credit, 'f', -1, 64) + ";" - result += strconv.FormatFloat(ub.SmsCredit, 'f', -1, 64) + ";" - result += strconv.FormatFloat(ub.Traffic, 'f', -1, 64) + ";" - result += strconv.FormatFloat(ub.VolumeDiscountSeconds, 'f', -1, 64) + ";" - result += strconv.FormatFloat(ub.ReceivedCallSeconds, 'f', -1, 64) + ";" - result += strconv.Itoa(ub.ResetDayOfTheMonth) + ";" - result += ub.TariffPlanId - if ub.MinuteBuckets != nil { - result += ";" - } - for i, mb := range ub.MinuteBuckets { - if i > 0 { - result += "," - } - result += mb.store() - } - return -} - -/* -De-serializes the user budget for the storage. Used for key-value storages. -*/ -func (ub *UserBudget) restore(input string) { - elements := strings.Split(input, ";") - ub.Credit, _ = strconv.ParseFloat(elements[0], 64) - ub.SmsCredit, _ = strconv.ParseFloat(elements[1], 64) - ub.Traffic, _ = strconv.ParseFloat(elements[2], 64) - ub.VolumeDiscountSeconds, _ = strconv.ParseFloat(elements[3], 64) - ub.ReceivedCallSeconds, _ = strconv.ParseFloat(elements[4], 64) - ub.ResetDayOfTheMonth, _ = strconv.Atoi(elements[5]) - ub.TariffPlanId = elements[6] - if len(elements) > 7 { - for _, mbs := range strings.Split(elements[7], ",") { - mb := &MinuteBucket{} - mb.restore(mbs) - ub.MinuteBuckets = append(ub.MinuteBuckets, mb) - } - } -} - /* Returns the tariff plan loading it from the storage if necessary. */ func (ub *UserBudget) getTariffPlan(storage StorageGetter) (tp *TariffPlan, err error) { - if ub.tariffPlan == nil { + if ub.tariffPlan == nil && ub.TariffPlanId != "" { ub.tariffPlan, err = storage.GetTariffPlan(ub.TariffPlanId) } return ub.tariffPlan, err @@ -150,7 +104,6 @@ func (ub *UserBudget) getSecondsForPrefix(sg StorageGetter, prefix string) (seco // log.Print("There are no minute buckets to check for user: ", ub.Id) return } - for _, mb := range ub.MinuteBuckets { d := mb.getDestination(sg) if d == nil { diff --git a/timespans/userbudget_test.go b/timespans/userbudget_test.go index 11eef1b73..4721b8744 100644 --- a/timespans/userbudget_test.go +++ b/timespans/userbudget_test.go @@ -53,19 +53,6 @@ func TestGetPricedSeconds(t *testing.T) { } } -func TestUserBudgetStoreRestore(t *testing.T) { - b1 := &MinuteBucket{Seconds: 10, Priority: 10, Price: 0.01, DestinationId: "nationale"} - b2 := &MinuteBucket{Seconds: 100, Priority: 20, Price: 0.0, DestinationId: "retea"} - seara := &TariffPlan{Id: "seara", SmsCredit: 100, MinuteBuckets: []*MinuteBucket{b1, b2}} - rifsBudget := &UserBudget{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, Credit: 21, tariffPlan: seara, ResetDayOfTheMonth: 10} - s := rifsBudget.store() - ub1 := &UserBudget{Id: "other"} - ub1.restore(s) - if ub1.store() != s { - t.Errorf("Expected %q was %q", s, ub1.store()) - } -} - func TestUserBudgetKyotoStore(t *testing.T) { getter, _ := NewKyotoStorage("test.kch") defer getter.Close()