diff --git a/cmd/cgr-balancer/cgr-balanncer.go b/cmd/cgr-balancer/cgr-balanncer.go index 6194fde3b..b39deeaa0 100644 --- a/cmd/cgr-balancer/cgr-balanncer.go +++ b/cmd/cgr-balancer/cgr-balanncer.go @@ -45,7 +45,7 @@ The function that gets the information from the raters using balancer. */ func GetCallCost(key *timespans.CallDescriptor, method string) (reply *timespans.CallCost) { balancerRWMutex.RLock() - defer balancerRWMutex + defer balancerRWMutex.RUnlock() err := errors.New("") //not nil value for err != nil { client := bal.Balance() @@ -67,6 +67,8 @@ func GetCallCost(key *timespans.CallDescriptor, method string) (reply *timespans The function that gets the information from the raters using balancer. */ func CallMethod(key *timespans.CallDescriptor, method string) (reply float64) { + balancerRWMutex.Lock() + defer balancerRWMutex.Unlock() err := errors.New("") //not nil value for err != nil { client := bal.Balance() diff --git a/cmd/cgr-balancer/http_responder.go b/cmd/cgr-balancer/http_responder.go index f015ef25d..578d79d12 100644 --- a/cmd/cgr-balancer/http_responder.go +++ b/cmd/cgr-balancer/http_responder.go @@ -30,30 +30,30 @@ type IncorrectParameters struct { } /* -curl "http://127.0.0.1:8000/getcost?cstmid=vdf&subj=rif&dest=0257" +curl "http://127.0.0.1:8000/getcost?tenant=vdf&subj=rif&dest=0257" */ func getCostHandler(w http.ResponseWriter, r *http.Request) { enc := json.NewEncoder(w) r.ParseForm() - cstmid, ok1 := r.Form["cstmid"] + tenant, ok1 := r.Form["tenant"] subj, ok2 := r.Form["subj"] dest, ok3 := r.Form["dest"] if !ok1 || !ok2 || !ok3 { enc.Encode(IncorrectParameters{"Incorrect parameters"}) return } - arg := ×pans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0]} + arg := ×pans.CallDescriptor{Tenant: tenant[0], Subject: subj[0], Destination: dest[0]} callCost := GetCallCost(arg, "Responder.GetCost") enc.Encode(callCost) } /* -curl "http://127.0.0.1:8000/debitbalance?cstmid=vdf&subj=rif&dest=0257@amount=100" +curl "http://127.0.0.1:8000/debitbalance?tenant=vdf&subj=rif&dest=0257@amount=100" */ func debitBalanceHandler(w http.ResponseWriter, r *http.Request) { enc := json.NewEncoder(w) r.ParseForm() - cstmid, ok1 := r.Form["cstmid"] + tenant, ok1 := r.Form["tenant"] subj, ok2 := r.Form["subj"] dest, ok3 := r.Form["dest"] amount_s, ok4 := r.Form["amount"] @@ -62,18 +62,18 @@ func debitBalanceHandler(w http.ResponseWriter, r *http.Request) { enc.Encode(IncorrectParameters{"Incorrect parameters"}) return } - arg := ×pans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0], Amount: amount} + arg := ×pans.CallDescriptor{Tenant: tenant[0], Subject: subj[0], Destination: dest[0], Amount: amount} result := CallMethod(arg, "Responder.DebitCents") enc.Encode(result) } /* -curl "http://127.0.0.1:8000/debitsms?cstmid=vdf&subj=rif&dest=0257@amount=100" +curl "http://127.0.0.1:8000/debitsms?tenant=vdf&subj=rif&dest=0257@amount=100" */ func debitSMSHandler(w http.ResponseWriter, r *http.Request) { enc := json.NewEncoder(w) r.ParseForm() - cstmid, ok1 := r.Form["cstmid"] + tenant, ok1 := r.Form["tenant"] subj, ok2 := r.Form["subj"] dest, ok3 := r.Form["dest"] amount_s, ok4 := r.Form["amount"] @@ -82,18 +82,18 @@ func debitSMSHandler(w http.ResponseWriter, r *http.Request) { enc.Encode(IncorrectParameters{"Incorrect parameters"}) return } - arg := ×pans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0], Amount: amount} + arg := ×pans.CallDescriptor{Tenant: tenant[0], Subject: subj[0], Destination: dest[0], Amount: amount} result := CallMethod(arg, "Responder.DebitSMS") enc.Encode(result) } /* -curl "http://127.0.0.1:8000/debitseconds?cstmid=vdf&subj=rif&dest=0257@amount=100" +curl "http://127.0.0.1:8000/debitseconds?tenant=vdf&subj=rif&dest=0257@amount=100" */ func debitSecondsHandler(w http.ResponseWriter, r *http.Request) { enc := json.NewEncoder(w) r.ParseForm() - cstmid, ok1 := r.Form["cstmid"] + tenant, ok1 := r.Form["tenant"] subj, ok2 := r.Form["subj"] dest, ok3 := r.Form["dest"] amount_s, ok4 := r.Form["amount"] @@ -102,18 +102,18 @@ func debitSecondsHandler(w http.ResponseWriter, r *http.Request) { enc.Encode(IncorrectParameters{"Incorrect parameters"}) return } - arg := ×pans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0], Amount: amount} + arg := ×pans.CallDescriptor{Tenant: tenant[0], Subject: subj[0], Destination: dest[0], Amount: amount} result := CallMethod(arg, "Responder.DebitSeconds") enc.Encode(result) } /* -curl "http://127.0.0.1:8000/getmaxsessiontime?cstmid=vdf&subj=rif&dest=0257@amount=100" +curl "http://127.0.0.1:8000/getmaxsessiontime?tenant=vdf&subj=rif&dest=0257@amount=100" */ func getMaxSessionTimeHandler(w http.ResponseWriter, r *http.Request) { enc := json.NewEncoder(w) r.ParseForm() - cstmid, ok1 := r.Form["cstmid"] + tenant, ok1 := r.Form["tenant"] subj, ok2 := r.Form["subj"] dest, ok3 := r.Form["dest"] amount_s, ok4 := r.Form["amount"] @@ -122,18 +122,18 @@ func getMaxSessionTimeHandler(w http.ResponseWriter, r *http.Request) { enc.Encode(IncorrectParameters{"Incorrect parameters"}) return } - arg := ×pans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0], Amount: amount} + arg := ×pans.CallDescriptor{Tenant: tenant[0], Subject: subj[0], Destination: dest[0], Amount: amount} result := CallMethod(arg, "Responder.GetMaxSessionTime") enc.Encode(result) } /* -curl "http://127.0.0.1:8000/addvolumediscountseconds?cstmid=vdf&subj=rif&dest=0257@amount=100" +curl "http://127.0.0.1:8000/addvolumediscountseconds?tenant=vdf&subj=rif&dest=0257@amount=100" */ func addVolumeDiscountSeconds(w http.ResponseWriter, r *http.Request) { enc := json.NewEncoder(w) r.ParseForm() - cstmid, ok1 := r.Form["cstmid"] + tenant, ok1 := r.Form["tenant"] subj, ok2 := r.Form["subj"] dest, ok3 := r.Form["dest"] amount_s, ok4 := r.Form["amount"] @@ -142,36 +142,36 @@ func addVolumeDiscountSeconds(w http.ResponseWriter, r *http.Request) { enc.Encode(IncorrectParameters{"Incorrect parameters"}) return } - arg := ×pans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0], Amount: amount} + arg := ×pans.CallDescriptor{Tenant: tenant[0], Subject: subj[0], Destination: dest[0], Amount: amount} result := CallMethod(arg, "Responder.AddVolumeDiscountSeconds") enc.Encode(result) } /* -curl "http://127.0.0.1:8000/resetvolumediscountseconds?cstmid=vdf&subj=rif&dest=0257" +curl "http://127.0.0.1:8000/resetvolumediscountseconds?tenant=vdf&subj=rif&dest=0257" */ func resetVolumeDiscountSeconds(w http.ResponseWriter, r *http.Request) { enc := json.NewEncoder(w) r.ParseForm() - cstmid, ok1 := r.Form["cstmid"] + tenant, ok1 := r.Form["tenant"] subj, ok2 := r.Form["subj"] dest, ok3 := r.Form["dest"] if !ok1 || !ok2 || !ok3 { enc.Encode(IncorrectParameters{"Incorrect parameters"}) return } - arg := ×pans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0]} + arg := ×pans.CallDescriptor{Tenant: tenant[0], Subject: subj[0], Destination: dest[0]} result := CallMethod(arg, "Responder.ResetVolumeDiscountSeconds") enc.Encode(result) } /* -curl "http://127.0.0.1:8000/addrecievedcallseconds?cstmid=vdf&subj=rif&dest=0257@amount=100" +curl "http://127.0.0.1:8000/addrecievedcallseconds?tenant=vdf&subj=rif&dest=0257@amount=100" */ func addRecievedCallSeconds(w http.ResponseWriter, r *http.Request) { enc := json.NewEncoder(w) r.ParseForm() - cstmid, ok1 := r.Form["cstmid"] + tenant, ok1 := r.Form["tenant"] subj, ok2 := r.Form["subj"] dest, ok3 := r.Form["dest"] amount_s, ok4 := r.Form["amount"] @@ -180,25 +180,25 @@ func addRecievedCallSeconds(w http.ResponseWriter, r *http.Request) { enc.Encode(IncorrectParameters{"Incorrect parameters"}) return } - arg := ×pans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0], Amount: amount} + arg := ×pans.CallDescriptor{Tenant: tenant[0], Subject: subj[0], Destination: dest[0], Amount: amount} result := CallMethod(arg, "Responder.AddRecievedCallSeconds") enc.Encode(result) } /* -curl "http://127.0.0.1:8000/resetuserbudget?cstmid=vdf&subj=rif&dest=0257" +curl "http://127.0.0.1:8000/resetuserbudget?tenant=vdf&subj=rif&dest=0257" */ func resetUserBudget(w http.ResponseWriter, r *http.Request) { enc := json.NewEncoder(w) r.ParseForm() - cstmid, ok1 := r.Form["cstmid"] + tenant, ok1 := r.Form["tenant"] subj, ok2 := r.Form["subj"] dest, ok3 := r.Form["dest"] if !ok1 || !ok2 || !ok3 { enc.Encode(IncorrectParameters{"Incorrect parameters"}) return } - arg := ×pans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0]} + arg := ×pans.CallDescriptor{Tenant: tenant[0], Subject: subj[0], Destination: dest[0]} result := CallMethod(arg, "Responder.ResetUserBudget") enc.Encode(result) } diff --git a/cmd/cgr-console/cgr-console.go b/cmd/cgr-console/cgr-console.go index 4f16929ac..fbc43055e 100644 --- a/cmd/cgr-console/cgr-console.go +++ b/cmd/cgr-console/cgr-console.go @@ -29,14 +29,15 @@ import ( ) var ( - server = flag.String("server", "127.0.0.1:2001", "server address host:port") - tor = flag.String("tor", "0", "Type of record") - cstmid = flag.String("cstmid", "vdf", "Customer identificator") - subject = flag.String("subject", "rif", "The client who made the call") - dest = flag.String("dest", "0256", "Destination prefix") - ts = flag.String("ts", "2012-02-09T00:00:00Z", "Time start") - te = flag.String("te", "2012-02-09T00:10:00Z", "Time end") - amount = flag.Float64("amount", 100, "Amount for different operations") + server = flag.String("server", "127.0.0.1:2001", "server address host:port") + tor = flag.String("tor", "0", "Type of record") + direction = flag.String("direction", "OUT", "Call direction") + tenant = flag.String("tenant", "vdf", "Tenant identificator") + subject = flag.String("subject", "rif", "The client who made the call") + dest = flag.String("dest", "0256", "Call destination") + ts = flag.String("ts", "2012-02-09T00:00:00Z", "Time start") + te = flag.String("te", "2012-02-09T00:10:00Z", "Time end") + amount = flag.Float64("amount", 100, "Amount for different operations") ) func main() { @@ -56,13 +57,15 @@ func main() { log.Fatal("Time end format is invalid: ", err) } - cd := ×pans.CallDescriptor{TOR: *tor, - CstmId: *cstmid, - Subject: *subject, - DestinationPrefix: *dest, - TimeStart: timestart, - TimeEnd: timeend, - Amount: *amount, + cd := ×pans.CallDescriptor{ + Direction: *direction, + TOR: *tor, + Tenant: *tenant, + Subject: *subject, + Destination: *dest, + TimeStart: timestart, + TimeEnd: timeend, + Amount: *amount, } switch flag.Arg(0) { diff --git a/cmd/cgr-loader/actions.go b/cmd/cgr-loader/actions.go index 95944dae1..e4ae4ff5b 100644 --- a/cmd/cgr-loader/actions.go +++ b/cmd/cgr-loader/actions.go @@ -75,17 +75,23 @@ func loadActions() { if record[5] == timespans.ABSOLUTE { price = value } - weight, err := strconv.ParseFloat(record[7], 64) + minutesWeight, err := strconv.ParseFloat(record[7], 64) if err != nil { - log.Printf("Could not parse action units: %v", err) + log.Printf("Could not parse action minutes weight: %v", err) + continue + } + weight, err := strconv.ParseFloat(record[8], 64) + if err != nil { + log.Printf("Could not parse action weight: %v", err) continue } a = ×pans.Action{ ActionType: record[1], BalanceId: record[2], + Weight: weight, MinuteBucket: ×pans.MinuteBucket{ Seconds: units, - Weight: weight, + Weight: minutesWeight, Price: price, Percent: percent, DestinationId: record[4], @@ -120,9 +126,15 @@ func loadActionTimings() { log.Printf("Could not load the timing for tag: %v", record[2]) continue } + weight, err := strconv.ParseFloat(record[3], 64) + if err != nil { + log.Printf("Could not parse action timing weight: %v", err) + continue + } for _, t := range ts { at := ×pans.ActionTiming{ - Tag: record[2], + Tag: record[2], + Weight: weight, Timing: ×pans.Interval{ Months: t.Months, MonthDays: t.MonthDays, @@ -160,11 +172,17 @@ func loadActionTriggers() { log.Printf("Could not parse action trigger value: %v", err) continue } + weight, err := strconv.ParseFloat(record[5], 64) + if err != nil { + log.Printf("Could not parse action trigger weight: %v", err) + continue + } at := ×pans.ActionTrigger{ BalanceId: record[1], ThresholdValue: value, DestinationId: record[3], ActionsId: record[4], + Weight: weight, } actionsTriggers[tag] = append(actionsTriggers[tag], at) } diff --git a/cmd/stress/cgr-balancerstress/cgr-balancerstress.go b/cmd/stress/cgr-balancerstress/cgr-balancerstress.go index f67739400..2bdac5e6b 100644 --- a/cmd/stress/cgr-balancerstress/cgr-balancerstress.go +++ b/cmd/stress/cgr-balancerstress/cgr-balancerstress.go @@ -37,7 +37,7 @@ func main() { flag.Parse() t1 := time.Date(2012, time.February, 02, 17, 30, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 02, 18, 30, 0, 0, time.UTC) - cd := timespans.CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2} + cd := timespans.CallDescriptor{Direction: "OUT", TOR: "0", Tenant: "vdf", Subject: "rif", Destination: "0256", TimeStart: t1, TimeEnd: t2} result := timespans.CallCost{} client, err := jsonrpc.Dial("tcp", *balancer) if err != nil { diff --git a/cmd/stress/cgr-balancerstress/cgr-balancerstress.py b/cmd/stress/cgr-balancerstress/cgr-balancerstress.py index de7f329a8..7273c55b0 100644 --- a/cmd/stress/cgr-balancerstress/cgr-balancerstress.py +++ b/cmd/stress/cgr-balancerstress/cgr-balancerstress.py @@ -43,7 +43,7 @@ class JSONClient(object): rpc =JSONClient(("127.0.0.1", 2001)) -cd = {"Tor":0, "CstmId": "vdf", "Subject": "rif", "DestinationPrefix": "0256", "TimeStart": "2012-02-02T17:30:00Z", "TimeEnd": "2012-02-02T18:30:00Z"} +cd = {"Direction":"OUT", "TOR":"0", "Tenant": "vdf", "Subject": "rif", "DestinationPrefix": "0256", "TimeStart": "2012-02-02T17:30:00Z", "TimeEnd": "2012-02-02T18:30:00Z"} # alternative to the above s = socket.create_connection(("127.0.0.1", 2001)) diff --git a/cmd/stress/cgr-raterstress/cgr-raterstress.go b/cmd/stress/cgr-raterstress/cgr-raterstress.go index 6c7c40690..7a9f71b1b 100644 --- a/cmd/stress/cgr-raterstress/cgr-raterstress.go +++ b/cmd/stress/cgr-raterstress/cgr-raterstress.go @@ -34,7 +34,7 @@ func main() { flag.Parse() t1 := time.Date(2012, time.February, 02, 17, 30, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 02, 18, 30, 0, 0, time.UTC) - cd := timespans.CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2} + cd := timespans.CallDescriptor{Direction: "OUT", TOR: "0", Tenant: "vdf", Subject: "rif", Destination: "0256", TimeStart: t1, TimeEnd: t2} result := timespans.CallCost{} client, _ := jsonrpc.Dial("tcp", "localhost:5090") i := 0 diff --git a/cmd/stress/cgr-spansstress/cgr-spansstress.go b/cmd/stress/cgr-spansstress/cgr-spansstress.go index e58e445a2..199c0cc20 100644 --- a/cmd/stress/cgr-spansstress/cgr-spansstress.go +++ b/cmd/stress/cgr-spansstress/cgr-spansstress.go @@ -47,13 +47,12 @@ func main() { t1 := time.Date(2012, time.February, 02, 17, 30, 0, 0, time.UTC) t2 := time.Date(2012, time.February, 02, 18, 30, 0, 0, time.UTC) - cd := timespans.CallDescriptor{CstmId: "vdf", Subject: "rif", DestinationPrefix: "0256", TimeStart: t1, TimeEnd: t2} + cd := timespans.CallDescriptor{Direction: "OUT", TOR: "0", Tenant: "vdf", Subject: "rif", Destination: "0256", TimeStart: t1, TimeEnd: t2} - //getter, _ := timespans.NewRedisStorage("", 10) - getter, err := timespans.NewKyotoStorage("storage.kch") + getter, err := timespans.NewRedisStorage("", 10) defer getter.Close() - cd.SetStorageGetter(getter) + timespans.SetStorageGetter(getter) log.Printf("Runnning %d cycles...", *runs) var result *timespans.CallCost diff --git a/sessionmanager/event.go b/sessionmanager/event.go index 443bb2244..ae2ea9f6e 100644 --- a/sessionmanager/event.go +++ b/sessionmanager/event.go @@ -31,6 +31,6 @@ type Event interface { GetDestination() string GetTOR() string GetUUID() string - GetCstmId() string + GetTenant() string GetStartTime() (time.Time, error) } diff --git a/sessionmanager/fsevent.go b/sessionmanager/fsevent.go index e820d10a0..5ac712625 100644 --- a/sessionmanager/fsevent.go +++ b/sessionmanager/fsevent.go @@ -94,7 +94,7 @@ func (fsev *FSEvent) GetTOR() string { func (fsev *FSEvent) GetUUID() string { return fsev.Fields[UUID] } -func (fsev *FSEvent) GetCstmId() string { +func (fsev *FSEvent) GetTenant() string { return fsev.Fields[CSTMID] } func (fsev *FSEvent) GetStartTime() (t time.Time, err error) { diff --git a/sessionmanager/postgreslogger.go b/sessionmanager/postgreslogger.go index d2d6ad12d..bc5b7b5b7 100644 --- a/sessionmanager/postgreslogger.go +++ b/sessionmanager/postgreslogger.go @@ -51,9 +51,9 @@ func (psl *PostgresLogger) Log(uuid string, cc *timespans.CallCost) { _, err = psl.db.Exec(fmt.Sprintf("INSERT INTO callcosts VALUES ('%s', '%s', '%s', '%s', '%s', %v, %v, '%s')", uuid, cc.TOR, - cc.CstmId, + cc.Tenant, cc.Subject, - cc.DestinationPrefix, + cc.Destination, cc.Cost, cc.ConnectFee, tss)) diff --git a/sessionmanager/session.go b/sessionmanager/session.go index ac993d1ee..b3fc9ded2 100644 --- a/sessionmanager/session.go +++ b/sessionmanager/session.go @@ -46,11 +46,13 @@ func NewSession(ev Event, sm SessionManager) (s *Session) { log.Print("Error parsing answer event start time, using time.Now!") startTime = time.Now() } - cd := ×pans.CallDescriptor{TOR: ev.GetTOR(), - CstmId: ev.GetCstmId(), - Subject: ev.GetSubject(), - DestinationPrefix: ev.GetDestination(), - TimeStart: startTime} + cd := ×pans.CallDescriptor{ + Direction: ev.GetDirection(), + TOR: ev.GetTOR(), + Tenant: ev.GetTenant(), + Subject: ev.GetSubject(), + Destination: ev.GetDestination(), + TimeStart: startTime} s = &Session{uuid: ev.GetUUID(), callDescriptor: cd, stopDebit: make(chan byte, 2)} //buffer it for multiple close signals @@ -106,7 +108,7 @@ func (s *Session) Disconnect() { // Nice print for session func (s *Session) String() string { - return fmt.Sprintf("%v: %s -> %s", s.callDescriptor.TimeStart, s.callDescriptor.Subject, s.callDescriptor.DestinationPrefix) + return fmt.Sprintf("%v: %s -> %s", s.callDescriptor.TimeStart, s.callDescriptor.Subject, s.callDescriptor.Destination) } // diff --git a/sessionmanager/sessiondelegate.go b/sessionmanager/sessiondelegate.go index 8b42ee364..39c5e4eac 100644 --- a/sessionmanager/sessiondelegate.go +++ b/sessionmanager/sessiondelegate.go @@ -50,6 +50,7 @@ type DirectSessionDelegate struct { } func NewDirectSessionDelegate(storageGetter timespans.StorageGetter) *DirectSessionDelegate { + timespans.SetStorageGetter(storageGetter) return &DirectSessionDelegate{storageGetter} } @@ -98,23 +99,24 @@ func (dsd *DirectSessionDelegate) OnChannelHangupComplete(ev Event, s *Session) } } if cost > 0 { - cd := ×pans.CallDescriptor{TOR: lastCC.TOR, - CstmId: lastCC.CstmId, - Subject: lastCC.CstmId, - DestinationPrefix: lastCC.DestinationPrefix, - Amount: -cost, + cd := ×pans.CallDescriptor{ + TOR: lastCC.TOR, + Tenant: lastCC.Tenant, + Subject: lastCC.Subject, + Destination: lastCC.Destination, + Amount: -cost, } - cd.SetStorageGetter(dsd.storageGetter) cd.DebitCents() } if seconds > 0 { - cd := ×pans.CallDescriptor{TOR: lastCC.TOR, - CstmId: lastCC.CstmId, - Subject: lastCC.CstmId, - DestinationPrefix: lastCC.DestinationPrefix, - Amount: -seconds, + cd := ×pans.CallDescriptor{ + TOR: lastCC.TOR, + Tenant: lastCC.Tenant, + Subject: lastCC.Subject, + Destination: lastCC.Destination, + Amount: -seconds, } - cd.SetStorageGetter(dsd.storageGetter) + cd.DebitSeconds() } lastCC.Cost -= cost @@ -122,7 +124,7 @@ func (dsd *DirectSessionDelegate) OnChannelHangupComplete(ev Event, s *Session) } func (dsd *DirectSessionDelegate) LoopAction(s *Session, cd *timespans.CallDescriptor) { - cd.SetStorageGetter(dsd.storageGetter) + timespans.SetStorageGetter(dsd.storageGetter) cc, err := cd.Debit() if err != nil { log.Printf("Could not complete debit opperation: %v", err) @@ -218,11 +220,12 @@ func (rsd *RPCSessionDelegate) OnChannelHangupComplete(ev Event, s *Session) { } } if cost > 0 { - cd := ×pans.CallDescriptor{TOR: lastCC.TOR, - CstmId: lastCC.CstmId, - Subject: lastCC.CstmId, - DestinationPrefix: lastCC.DestinationPrefix, - Amount: -cost, + cd := ×pans.CallDescriptor{ + TOR: lastCC.TOR, + Tenant: lastCC.Tenant, + Subject: lastCC.Subject, + Destination: lastCC.Destination, + Amount: -cost, } var response float64 err := client.Call("Responder.DebitCents", cd, &response) @@ -231,11 +234,12 @@ func (rsd *RPCSessionDelegate) OnChannelHangupComplete(ev Event, s *Session) { } } if seconds > 0 { - cd := ×pans.CallDescriptor{TOR: lastCC.TOR, - CstmId: lastCC.CstmId, - Subject: lastCC.CstmId, - DestinationPrefix: lastCC.DestinationPrefix, - Amount: -seconds, + cd := ×pans.CallDescriptor{ + TOR: lastCC.TOR, + Tenant: lastCC.Tenant, + Subject: lastCC.Subject, + Destination: lastCC.Destination, + Amount: -seconds, } var response float64 err := client.Call("Responder.DebitSeconds", cd, &response) diff --git a/timespans/action.go b/timespans/action.go index f5bea5c96..ddf971271 100644 --- a/timespans/action.go +++ b/timespans/action.go @@ -67,8 +67,8 @@ func setPostpaidAction(ub *UserBalance, a *Action) (err error) { } func resetPostpaidAction(ub *UserBalance, a *Action) (err error) { - ub.Type = UB_TYPE_POSTPAID - return + genericReset(ub) + return setPostpaidAction(ub, a) } func setPrepaidAction(ub *UserBalance, a *Action) (err error) { @@ -77,8 +77,8 @@ func setPrepaidAction(ub *UserBalance, a *Action) (err error) { } func resetPrepaidAction(ub *UserBalance, a *Action) (err error) { - ub.Type = UB_TYPE_PREPAID - return + genericReset(ub) + return setPrepaidAction(ub, a) } func topupResetAction(ub *UserBalance, a *Action) (err error) { @@ -99,14 +99,35 @@ func topupAction(ub *UserBalance, a *Action) (err error) { } func debitAction(ub *UserBalance, a *Action) (err error) { + switch a.ActionType { + case CREDIT: + ub.debitMoneyBalance(a.Units) + case SMS: + ub.debitSMSBalance(a.Units) + case MINUTES: + ub.debitMinuteBucket(a.MinuteBucket) + case TRAFFIC: + ub.debitTrafficBalance(a.Units) + case TRAFFIC_TIME: + ub.debitTrafficTimeBalance(a.Units) + } return } func resetCountersAction(ub *UserBalance, a *Action) (err error) { - //ub.UnitsCounters + ub.UnitCounters = make([]*UnitsCounter, 0) return } +func genericReset(ub *UserBalance) { + for k, _ := range ub.BalanceMap { + ub.BalanceMap[k] = 0 + } + ub.MinuteBuckets = make([]*MinuteBucket, 0) + ub.UnitCounters = make([]*UnitsCounter, 0) + ub.resetActionTriggers() +} + // Structure to store actions according to weight type ActionPriotityList []*Action diff --git a/timespans/calldesc.go b/timespans/calldesc.go index d83c203e5..612bc682e 100644 --- a/timespans/calldesc.go +++ b/timespans/calldesc.go @@ -342,6 +342,7 @@ func (cd *CallDescriptor) Debit() (cc *CallCost, err error) { log.Printf("error getting cost %v", err) } if userBalance, err := cd.getUserBalance(); err == nil && userBalance != nil { + defer storageGetter.SetUserBalance(userBalance) if cc.Cost != 0 || cc.ConnectFee != 0 { userBalance.debitMoneyBalance(cc.Cost + cc.ConnectFee) } @@ -362,6 +363,7 @@ func (cd *CallDescriptor) DebitCents() (left float64, err error) { userBalancesRWMutex.Lock() defer userBalancesRWMutex.Unlock() if userBalance, err := cd.getUserBalance(); err == nil && userBalance != nil { + defer storageGetter.SetUserBalance(userBalance) return userBalance.debitMoneyBalance(cd.Amount), nil } return 0.0, err @@ -375,7 +377,8 @@ func (cd *CallDescriptor) DebitSMS() (left float64, err error) { userBalancesRWMutex.Lock() defer userBalancesRWMutex.Unlock() if userBalance, err := cd.getUserBalance(); err == nil && userBalance != nil { - return userBalance.debitSMSBuget(cd.Amount) + defer storageGetter.SetUserBalance(userBalance) + return userBalance.debitSMSBalance(cd.Amount) } return 0, err } @@ -388,6 +391,7 @@ func (cd *CallDescriptor) DebitSeconds() (err error) { userBalancesRWMutex.Lock() defer userBalancesRWMutex.Unlock() if userBalance, err := cd.getUserBalance(); err == nil && userBalance != nil { + defer storageGetter.SetUserBalance(userBalance) return userBalance.debitMinutesBalance(cd.Amount, cd.Destination) } return err diff --git a/timespans/minute_buckets.go b/timespans/minute_buckets.go index 22402039d..a819330dc 100644 --- a/timespans/minute_buckets.go +++ b/timespans/minute_buckets.go @@ -42,6 +42,14 @@ func (mb *MinuteBucket) GetSecondsForCredit(credit float64) (seconds float64) { return } +// +func (mb *MinuteBucket) Equal(o *MinuteBucket) bool { + return mb.DestinationId == o.DestinationId && + mb.Weight == o.Weight && + mb.Price == o.Price && + mb.Percent == o.Percent +} + /* Structure to store minute buckets according to weight, precision or price. */ diff --git a/timespans/minute_buckets_test.go b/timespans/minute_buckets_test.go index bc8b38850..f2cfcb468 100644 --- a/timespans/minute_buckets_test.go +++ b/timespans/minute_buckets_test.go @@ -54,3 +54,12 @@ func TestMinutBucketSortPrice(t *testing.T) { t.Error("Buckets not sorted by price!") } } + +func TestMinutBucketEqual(t *testing.T) { + mb1 := &MinuteBucket{Weight: 1, precision: 1, Price: 1, Percent: 1, DestinationId: ""} + mb2 := &MinuteBucket{Weight: 1, precision: 1, Price: 1, Percent: 1, DestinationId: ""} + mb3 := &MinuteBucket{Weight: 1, precision: 1, Price: 2, Percent: 1, DestinationId: ""} + if !mb1.Equal(mb2) || mb2.Equal(mb3) { + t.Error("Equal failure!", mb1, mb2, mb3) + } +} diff --git a/timespans/userbalance.go b/timespans/userbalance.go index 6ccbf57ad..2b9a21592 100644 --- a/timespans/userbalance.go +++ b/timespans/userbalance.go @@ -53,7 +53,7 @@ type UserBalance struct { Type string // prepaid-postpaid BalanceMap map[string]float64 MinuteBuckets []*MinuteBucket - UnitsCounters []*UnitsCounter + UnitCounters []*UnitsCounter ActionTriggers ActionTriggerPriotityList } @@ -102,10 +102,20 @@ Debits some amount of user's money credit. Returns the remaining credit in user' */ func (ub *UserBalance) debitMoneyBalance(amount float64) float64 { ub.BalanceMap[CREDIT] -= amount - storageGetter.SetUserBalance(ub) + return ub.BalanceMap[CREDIT] } +// Debit seconds from specified minute bucket +func (ub *UserBalance) debitMinuteBucket(newMb *MinuteBucket) error { + for _, mb := range ub.MinuteBuckets { + if mb.Equal(newMb) { + mb.Seconds -= newMb.Seconds + } + } + return nil +} + /* Debits the received amount of seconds from user's minute buckets. All the appropriate buckets will be debited until all amount of minutes is consumed. @@ -150,7 +160,6 @@ func (ub *UserBalance) debitMinutesBalance(amount float64, prefix string) error break } } - storageGetter.SetUserBalance(ub) return nil } @@ -158,13 +167,30 @@ func (ub *UserBalance) debitMinutesBalance(amount float64, prefix string) error Debits some amount of user's SMS balance. Returns the remaining SMS in user's balance. If the amount is bigger than the balance than nothing wil be debited and an error will be returned */ -func (ub *UserBalance) debitSMSBuget(amount float64) (float64, error) { +func (ub *UserBalance) debitSMSBalance(amount float64) (float64, error) { + if ub.BalanceMap[SMS] < amount { + return ub.BalanceMap[SMS], new(AmountTooBig) + } + ub.BalanceMap[SMS] -= amount + + return ub.BalanceMap[SMS], nil +} + +func (ub *UserBalance) debitTrafficBalance(amount float64) (float64, error) { + if ub.BalanceMap[SMS] < amount { + return ub.BalanceMap[SMS], new(AmountTooBig) + } + ub.BalanceMap[SMS] -= amount + + return ub.BalanceMap[SMS], nil +} + +func (ub *UserBalance) debitTrafficTimeBalance(amount float64) (float64, error) { if ub.BalanceMap[SMS] < amount { return ub.BalanceMap[SMS], new(AmountTooBig) } ub.BalanceMap[SMS] -= amount - storageGetter.SetUserBalance(ub) return ub.BalanceMap[SMS], nil } @@ -193,7 +219,7 @@ func (ub *UserBalance) executeActionTriggers() { // the next reset (see RESET_TRIGGERS action type) continue } - for _, uc := range ub.UnitsCounters { + for _, uc := range ub.UnitCounters { if uc.BalanceId == at.BalanceId { if at.BalanceId == MINUTES && at.DestinationId != "" { // last check adds safty for _, mb := range uc.MinuteBuckets { @@ -241,7 +267,7 @@ Adds the specified amount of seconds. // } // } // } -// return storageGetter.SetUserBalance(ub) +// return // } /* @@ -260,7 +286,7 @@ Resets the user balance items to their tariff plan values. DestinationId: bucket.DestinationId} ub.MinuteBuckets = append(ub.MinuteBuckets, mb) } - err = storageGetter.SetUserBalance(ub) + err = } return } diff --git a/timespans/userbalance_test.go b/timespans/userbalance_test.go index fcca9dc18..e18fda960 100644 --- a/timespans/userbalance_test.go +++ b/timespans/userbalance_test.go @@ -162,7 +162,7 @@ func TestDebitMoreMinuteBalance(t *testing.T) { } } -func TestDebitPriceMinuteBalance(t *testing.T) { +func TestDebitPriceMinuteBalance0(t *testing.T) { b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.0, DestinationId: "NAT"} b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 1.0, DestinationId: "RET"} rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]float64{CREDIT: 21}} @@ -219,7 +219,7 @@ func TestDebitSMSBalance(t *testing.T) { b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.0, DestinationId: "NAT"} b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"} rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]float64{CREDIT: 21, SMS: 100}} - result, err := rifsBalance.debitSMSBuget(12) + result, err := rifsBalance.debitSMSBalance(12) if rifsBalance.BalanceMap[SMS] != 88 || result != rifsBalance.BalanceMap[SMS] || err != nil { t.Errorf("Expected %v was %v", 88, rifsBalance.BalanceMap[SMS]) } @@ -229,7 +229,7 @@ func TestDebitAllSMSBalance(t *testing.T) { b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.0, DestinationId: "NAT"} b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"} rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]float64{CREDIT: 21, SMS: 100}} - result, err := rifsBalance.debitSMSBuget(100) + result, err := rifsBalance.debitSMSBalance(100) if rifsBalance.BalanceMap[SMS] != 0 || result != rifsBalance.BalanceMap[SMS] || err != nil { t.Errorf("Expected %v was %v", 0, rifsBalance.BalanceMap[SMS]) } @@ -239,7 +239,7 @@ func TestDebitMoreSMSBalance(t *testing.T) { b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.0, DestinationId: "NAT"} b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"} rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]float64{CREDIT: 21, SMS: 100}} - result, err := rifsBalance.debitSMSBuget(110) + result, err := rifsBalance.debitSMSBalance(110) if rifsBalance.BalanceMap[SMS] != 100 || result != rifsBalance.BalanceMap[SMS] || err == nil { t.Errorf("Expected %v was %v", 100, rifsBalance.BalanceMap[SMS]) } @@ -249,7 +249,7 @@ func TestDebitNegativeSMSBalance(t *testing.T) { b1 := &MinuteBucket{Seconds: 10, Weight: 10, Price: 0.0, DestinationId: "NAT"} b2 := &MinuteBucket{Seconds: 100, Weight: 20, Price: 0.0, DestinationId: "RET"} rifsBalance := &UserBalance{Id: "other", MinuteBuckets: []*MinuteBucket{b1, b2}, BalanceMap: map[string]float64{CREDIT: 21, SMS: 100}} - result, err := rifsBalance.debitSMSBuget(-15) + result, err := rifsBalance.debitSMSBalance(-15) if rifsBalance.BalanceMap[SMS] != 115 || result != rifsBalance.BalanceMap[SMS] || err != nil { t.Errorf("Expected %v was %v", 115, rifsBalance.BalanceMap[SMS]) }