pulled the debit methods in the api interface

This commit is contained in:
Radu Ioan Fericean
2012-02-24 13:14:28 +02:00
parent 4b1f488444
commit 1c88344a81
6 changed files with 170 additions and 25 deletions

View File

@@ -1,11 +1,12 @@
package main
import(
import (
"encoding/json"
"fmt"
"github.com/rif/cgrates/timespans"
"log"
"net/http"
"encoding/json"
"github.com/rif/cgrates/timespans"
"strconv"
)
type IncorrectParameters struct {
@@ -30,20 +31,83 @@ func getCostHandler(w http.ResponseWriter, r *http.Request) {
enc := json.NewEncoder(w)
r.ParseForm()
cstmid, ok1 := r.Form["cstmid"]
subj, ok2 :=r.Form["subj"]
subj, ok2 := r.Form["subj"]
dest, ok3 := r.Form["dest"]
if !ok1 || !ok2 || !ok3 {
enc.Encode(IncorrectParameters{"Incorrect parameters"})
return
}
arg := &timespans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0]}
callCost := CallRater(arg)
callCost := GetCost(arg)
enc.Encode(callCost)
}
func listenToHttpRequests(){
/*
curl "http://127.0.0.1:8000/getcost?cstmid=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"]
subj, ok2 := r.Form["subj"]
dest, ok3 := r.Form["dest"]
amount_s, ok4 := r.Form["amount"]
amount, err := strconv.ParseFloat(amount_s[0], 64)
if !ok1 || !ok2 || !ok3 || ok4 || err != nil {
enc.Encode(IncorrectParameters{"Incorrect parameters"})
return
}
arg := &timespans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0], Amount: amount}
result := Debit(arg, "Storage.DebitCents")
enc.Encode(result)
}
/*
curl "http://127.0.0.1:8000/getcost?cstmid=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"]
subj, ok2 := r.Form["subj"]
dest, ok3 := r.Form["dest"]
amount_s, ok4 := r.Form["amount"]
amount, err := strconv.ParseFloat(amount_s[0], 64)
if !ok1 || !ok2 || !ok3 || !ok4 || err != nil {
enc.Encode(IncorrectParameters{"Incorrect parameters"})
return
}
arg := &timespans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0], Amount: amount}
result := Debit(arg, "Storage.DebitSMS")
enc.Encode(result)
}
/*
curl "http://127.0.0.1:8000/getcost?cstmid=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"]
subj, ok2 := r.Form["subj"]
dest, ok3 := r.Form["dest"]
amount_s, ok4 := r.Form["amount"]
amount, err := strconv.ParseFloat(amount_s[0], 64)
if !ok1 || !ok2 || !ok3 || !ok4 || err != nil {
enc.Encode(IncorrectParameters{"Incorrect parameters"})
return
}
arg := &timespans.CallDescriptor{CstmId: cstmid[0], Subject: subj[0], DestinationPrefix: dest[0], Amount: amount}
result := Debit(arg, "Storage.DebitSeconds")
enc.Encode(result)
}
func listenToHttpRequests() {
http.HandleFunc("/", statusHandler)
http.HandleFunc("/getcost", getCostHandler)
http.HandleFunc("/debitbalance", debitBalanceHandler)
http.HandleFunc("/debitsms", debitSMSHandler)
http.HandleFunc("/debitseconds", debitSecondsHandler)
log.Print("The server is listening on ", *httpApiAddress)
http.ListenAndServe(*httpApiAddress, nil)
}

View File

@@ -2,25 +2,24 @@ package main
import (
"errors"
"flag"
"github.com/rif/cgrates/timespans"
"log"
//"runtime"
"runtime"
"time"
"flag"
)
var (
raterAddress = flag.String("rateraddr", "127.0.0.1:2000", "Rater server address (localhost:2000)")
jsonRpcAddress = flag.String("jsonrpcaddr", "127.0.0.1:2001", "Json RPC server address (localhost:2001)")
httpApiAddress = flag.String("httpapiaddr", "127.0.0.1:8000", "Http API server address (localhost:2002)")
raterList *RaterList
raterAddress = flag.String("rateraddr", "127.0.0.1:2000", "Rater server address (localhost:2000)")
jsonRpcAddress = flag.String("jsonrpcaddr", "127.0.0.1:2001", "Json RPC server address (localhost:2001)")
httpApiAddress = flag.String("httpapiaddr", "127.0.0.1:8000", "Http API server address (localhost:2002)")
raterList *RaterList
)
/*
The function that gets the information from the raters using balancer.
*/
func CallRater(key *timespans.CallDescriptor) (reply *timespans.CallCost) {
func GetCost(key *timespans.CallDescriptor) (reply *timespans.CallCost) {
err := errors.New("") //not nil value
for err != nil {
client := raterList.Balance()
@@ -38,11 +37,29 @@ func CallRater(key *timespans.CallDescriptor) (reply *timespans.CallCost) {
return
}
/*
The function that gets the information from the raters using balancer.
*/
func Debit(key *timespans.CallDescriptor, method string) (reply float64) {
err := errors.New("") //not nil value
for err != nil {
client := raterList.Balance()
if client == nil {
log.Print("Waiting for raters to register...")
time.Sleep(1 * time.Second) // wait one second and retry
} else {
err = client.Call(method, *key, &reply)
if err != nil {
log.Printf("Got en error from rater: %v", err)
}
}
}
return
}
func main() {
flag.Parse()
//runtime.GOMAXPROCS(runtime.NumCPU() - 1)
runtime.GOMAXPROCS(runtime.NumCPU() - 1)
raterList = NewRaterList()
go StopSingnalHandler()

View File

@@ -2,10 +2,10 @@ package main
import (
"github.com/rif/cgrates/timespans"
"log"
"net"
"net/rpc"
"net/rpc/jsonrpc"
"log"
)
type Responder byte
@@ -13,9 +13,24 @@ type Responder byte
/*
RPC method thet provides the external RPC interface for getting the rating information.
*/
func (r *Responder) Get(arg timespans.CallDescriptor, replay *timespans.CallCost) error {
*replay = *CallRater(&arg)
return nil
func (r *Responder) GetGost(arg timespans.CallDescriptor, replay *timespans.CallCost) (err error) {
*replay = *GetCost(&arg)
return
}
func (r *Responder) DebitBalance(arg timespans.CallDescriptor, replay *float64) (err error) {
*replay = Debit(&arg, "Storage.DebitCents")
return
}
func (r *Responder) DebitSMS(arg timespans.CallDescriptor, replay *float64) (err error) {
*replay = Debit(&arg, "Storage.DebitSMS")
return
}
func (r *Responder) DebitSeconds(arg timespans.CallDescriptor, replay *float64) (err error) {
*replay = Debit(&arg, "Storage.DebitSeconds")
return
}
/*

View File

@@ -31,7 +31,31 @@ func (s *Storage) GetCost(cd timespans.CallDescriptor, reply *timespans.CallCost
descriptor.StorageGetter = s.sg
r, e := descriptor.GetCost()
*reply, err = *r, e
return nil
return err
}
func (s *Storage) DebitCents(cd timespans.CallDescriptor, reply *float64) (err error) {
descriptor := &cd
descriptor.StorageGetter = s.sg
r, e := descriptor.DebitCents()
*reply, err = r, e
return err
}
func (s *Storage) DebitSMS(cd timespans.CallDescriptor, reply *float64) (err error) {
descriptor := &cd
descriptor.StorageGetter = s.sg
r, e := descriptor.DebitSMS()
*reply, err = r, e
return err
}
func (s *Storage) DebitSeconds(cd timespans.CallDescriptor, reply *float64) (err error) {
descriptor := &cd
descriptor.StorageGetter = s.sg
e := descriptor.DebitSeconds()
*reply, err = 0.0, e
return err
}
/*

View File

@@ -36,6 +36,7 @@ type CallDescriptor struct {
TOR int
CstmId, Subject, DestinationPrefix string
TimeStart, TimeEnd time.Time
Amount float64
ActivationPeriods []*ActivationPeriod
StorageGetter StorageGetter
}
@@ -237,6 +238,27 @@ func (cd *CallDescriptor) GetMaxSessionTime(maxSessionSeconds int) (seconds int,
return 0, nil
}
func (cd *CallDescriptor) DebitCents() (left float64, err error) {
if userBudget, err := cd.StorageGetter.GetUserBudget(cd.Subject); err == nil && userBudget != nil {
return userBudget.debitMoneyBudget(cd.StorageGetter, cd.Amount), nil
}
return 0.0, err
}
func (cd *CallDescriptor) DebitSMS() (left float64, err error) {
if userBudget, err := cd.StorageGetter.GetUserBudget(cd.Subject); err == nil && userBudget != nil {
return userBudget.debitSMSBuget(cd.StorageGetter, cd.Amount)
}
return 0, err
}
func (cd *CallDescriptor) DebitSeconds() (err error) {
if userBudget, err := cd.StorageGetter.GetUserBudget(cd.Subject); err == nil && userBudget != nil {
return userBudget.debitMinutesBudget(cd.StorageGetter, cd.Amount, cd.DestinationPrefix)
}
return err
}
/*
The output structure that will be returned with the call cost information.
*/

View File

@@ -14,7 +14,7 @@ Structure conatining information about user's credit (minutes, cents, sms...).'
type UserBudget struct {
Id string
Credit float64
SmsCredit int
SmsCredit float64
ResetDayOfTheMonth int
TariffPlanId string
tariffPlan *TariffPlan
@@ -22,6 +22,9 @@ type UserBudget struct {
mux sync.RWMutex
}
/*
Error type for overflowed debit methods.
*/
type AmountTooBig byte
func (a AmountTooBig) Error() string {
@@ -52,7 +55,7 @@ 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.Itoa(ub.SmsCredit) + ";"
result += strconv.FormatFloat(ub.SmsCredit, 'f', -1, 64) + ";"
result += strconv.Itoa(ub.ResetDayOfTheMonth) + ";"
result += ub.TariffPlanId + ";"
for _, mb := range ub.MinuteBuckets {
@@ -72,7 +75,7 @@ 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.Atoi(elements[1])
ub.SmsCredit, _ = strconv.ParseFloat(elements[1], 64)
ub.ResetDayOfTheMonth, _ = strconv.Atoi(elements[2])
ub.TariffPlanId = elements[3]
for _, mbs := range elements[4 : len(elements)-1] {
@@ -193,7 +196,7 @@ func (ub *UserBudget) debitMinutesBudget(sg StorageGetter, amount float64, prefi
Debits some amount of user's SMS budget. Returns the remaining SMS in user's budget.
If the amount is bigger than the budget than nothing wil be debited and an error will be returned
*/
func (ub *UserBudget) debitSMSBuget(sg StorageGetter, amount int) (int, error) {
func (ub *UserBudget) debitSMSBuget(sg StorageGetter, amount float64) (float64, error) {
ub.mux.Lock()
defer ub.mux.Unlock()
if ub.SmsCredit < amount {