using years in get next activation time

This commit is contained in:
Radu Ioan Fericean
2012-07-26 16:25:12 +03:00
parent 47b4db61f0
commit 98967149b7
5 changed files with 253 additions and 77 deletions

View File

@@ -20,6 +20,7 @@ package main
import (
"code.google.com/p/goconf/conf"
"database/sql"
"flag"
"fmt"
"github.com/cgrates/cgrates/balancer"
@@ -156,6 +157,28 @@ func listenToHttpRequests() {
http.ListenAndServe(stats_listen, nil)
}
func startSessionManager(responder *timespans.Responder) {
var connector sessionmanager.Connector
if sm_rater == INTERNAL {
connector = responder
} else {
var client *rpc.Client
var err error
if sm_json {
client, err = jsonrpc.Dial("tcp", sm_rater)
} else {
client, err = rpc.Dial("tcp", sm_rater)
}
if err != nil {
timespans.Logger.Crit(fmt.Sprintf("Could not connect to rater: %v", err))
exitChan <- true
}
connector = &sessionmanager.RPCClientConnector{client}
}
sm := &sessionmanager.FSSessionManager{}
sm.Connect(&sessionmanager.SessionDelegate{connector}, sm_freeswitch_server, sm_freeswitch_pass)
}
func checkConfigSanity() {
if sm_enabled && rater_enabled && rater_balancer != DISABLED {
timespans.Logger.Crit("The session manager must not be enabled on a worker rater (change [rater]/balancer to disabled)!")
@@ -213,30 +236,34 @@ func main() {
}
if sm_enabled {
go func() {
var connector sessionmanager.Connector
if sm_rater == INTERNAL {
connector = responder
} else {
var client *rpc.Client
if sm_json {
client, err = jsonrpc.Dial("tcp", sm_rater)
} else {
client, err = rpc.Dial("tcp", sm_rater)
}
if err != nil {
timespans.Logger.Crit(fmt.Sprintf("Could not connect to rater: %v", err))
exitChan <- true
}
connector = &sessionmanager.RPCClientConnector{client}
}
sm := &sessionmanager.FSSessionManager{}
sm.Connect(&sessionmanager.SessionDelegate{connector}, sm_freeswitch_server, sm_freeswitch_pass)
}()
go startSessionManager(responder)
}
if mediator_enabled {
go startMediator()
db, err := sql.Open("postgres", fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s sslmode=disable", mediator_host, mediator_port, mediator_db, mediator_user, mediator_password))
//defer db.Close()
if err != nil {
timespans.Logger.Err(fmt.Sprintf("failed to open the database: %v", err))
}
var connector sessionmanager.Connector
if sm_rater == INTERNAL {
connector = responder
} else {
var client *rpc.Client
var err error
if sm_json {
client, err = jsonrpc.Dial("tcp", sm_rater)
} else {
client, err = rpc.Dial("tcp", sm_rater)
}
if err != nil {
timespans.Logger.Crit(fmt.Sprintf("Could not connect to rater: %v", err))
exitChan <- true
}
connector = &sessionmanager.RPCClientConnector{client}
}
m := &Mediator{connector, db}
_ = m
}
<-exitChan

View File

@@ -25,68 +25,61 @@ import (
"flag"
"fmt"
_ "github.com/bmizerany/pq"
"github.com/cgrates/cgrates/sessionmanager"
"github.com/cgrates/cgrates/timespans"
"log"
"net/rpc/jsonrpc"
"os"
"time"
)
func readDbRecord(db *sql.DB, searchedUUID string) (cc *timespans.CallCost, timespansText string, err error) {
row := db.QueryRow(fmt.Sprintf("SELECT * FROM callcosts WHERE uuid='%s'", searchedUUID))
type Mediator struct {
Connector sessionmanager.Connector
Db *sql.DB
}
/*func readDbRecord(db *sql.DB, searchedUUID string) (cc *timespans.CallCost, timespansText string, err error) {
}*/
func (m *Mediator) parseCSV() {
flag.Parse()
file, err := os.Open(mediator_cdr_file)
defer file.Close()
if err != nil {
log.Fatal(err)
}
csvReader := csv.NewReader(bufio.NewReader(file))
for record, err := csvReader.Read(); err == nil; record, err = csvReader.Read() {
uuid := record[10]
_ = uuid
t, _ := time.Parse("2012-05-21 17:48:20", record[5])
fmt.Println(t)
}
}
func (m *Mediator) GetCostsFromDB(searchedUUID string) (cc *timespans.CallCost, timespansText string, err error) {
row := m.Db.QueryRow(fmt.Sprintf("SELECT * FROM callcosts WHERE uuid='%s'", searchedUUID))
var uuid string
cc = &timespans.CallCost{}
err = row.Scan(&uuid, &cc.Direction, &cc.Tenant, &cc.TOR, &cc.Subject, &cc.Destination, &cc.Cost, &cc.ConnectFee, &timespansText)
return
}
func startMediator() {
flag.Parse()
useDB := true
file, err := os.Open(mediator_cdr_file)
defer file.Close()
if err != nil {
log.Fatal(err)
}
db, err := sql.Open("postgres", fmt.Sprintf("host=%s port=%s dbname=%s user=%s password=%s sslmode=disable", mediator_host, mediator_port, mediator_db, mediator_user, mediator_password))
defer db.Close()
if err != nil {
log.Printf("failed to open the database: %v", err)
useDB = false
}
csvReader := csv.NewReader(bufio.NewReader(file))
client, err := jsonrpc.Dial("tcp", "localhost:2001")
useRPC := true
if err != nil {
log.Printf("Could not connect to rater server: %v!", err)
useRPC = false
}
for record, err := csvReader.Read(); err == nil; record, err = csvReader.Read() {
uuid := record[10]
t, _ := time.Parse("2012-05-21 17:48:20", record[5])
fmt.Println(t)
if useDB {
cc, timespansText, err := readDbRecord(db, uuid)
if err != nil && useRPC {
// try getting the price from the rater
tenant := record[0]
subject := record[1]
dest := record[2]
t1, _ := time.Parse("2012-05-21 17:48:20", record[5])
t2, _ := time.Parse("2012-05-21 17:48:20", record[6])
cd := timespans.CallDescriptor{
Direction: "OUT",
Tenant: tenant,
TOR: "0",
Subject: subject,
Destination: dest,
TimeStart: t1,
TimeEnd: t2}
client.Call("Responder.GetCost", cd, cc)
}
_ = timespansText
//log.Print(cc, timespansText)
}
}
func (m *Mediator) GetCostsFromRater(record []string) (cc *timespans.CallCost, err error) {
tenant := record[0]
subject := record[1]
dest := record[2]
t1, _ := time.Parse("2012-05-21 17:48:20", record[5])
t2, _ := time.Parse("2012-05-21 17:48:20", record[6])
cd := timespans.CallDescriptor{
Direction: "OUT",
Tenant: tenant,
TOR: "0",
Subject: subject,
Destination: dest,
TimeStart: t1,
TimeEnd: t2}
err = m.Connector.GetCost(cd, cc)
return
}

View File

@@ -30,6 +30,7 @@ const (
)
type Connector interface {
GetCost(timespans.CallDescriptor, *timespans.CallCost) error
Debit(timespans.CallDescriptor, *timespans.CallCost) error
DebitCents(timespans.CallDescriptor, *float64) error
DebitSeconds(timespans.CallDescriptor, *float64) error
@@ -40,6 +41,10 @@ type RPCClientConnector struct {
Client *rpc.Client
}
func (rcc *RPCClientConnector) GetCost(cd timespans.CallDescriptor, cc *timespans.CallCost) error {
return rcc.Client.Call("Responder.GetCost", cd, cc)
}
func (rcc *RPCClientConnector) Debit(cd timespans.CallDescriptor, cc *timespans.CallCost) error {
return rcc.Client.Call("Responder.Debit", cd, cc)
}

View File

@@ -112,16 +112,16 @@ MONTHS:
if t.Equal(now) || t.After(now) {
h, m, s := t.Clock()
t = time.Date(now.Year(), now.Month(), t.Day(), h, m, s, 0, time.Local)
return
goto YEARS
}
if x+1 < len(i.Months) { // today was found in the list, jump to the next grater day
if x+1 < len(i.Months) { // this month was found in the list so jump to next available month
m = i.Months[x+1]
// reset the monthday
if i.MonthDays != nil {
t = time.Date(t.Year(), t.Month(), i.MonthDays[0], t.Hour(), t.Minute(), t.Second(), 0, t.Location())
}
}
} else { // today was not found in the list, x is the first greater day
} else { // this month was not found in the list, x is the first greater month
m = i.Months[x]
// reset the monthday
if i.MonthDays != nil {
@@ -132,6 +132,45 @@ MONTHS:
h, min, s := t.Clock()
t = time.Date(now.Year(), m, t.Day(), h, min, s, 0, time.Local)
}
YEARS:
if i.Years != nil && len(i.Years) > 0 {
i.Years.Sort()
now := time.Now()
x := sort.Search(len(i.Years), func(x int) bool { return i.Years[x] >= now.Year() })
y = i.Years[0]
if x < len(i.Years) {
if i.Years[x] == now.Year() {
if t.Equal(now) || t.After(now) {
h, m, s := t.Clock()
t = time.Date(now.Year(), t.Month(), t.Day(), h, m, s, 0, time.Local)
return
}
if x+1 < len(i.Years) { // this year was found in the list so jump to next available year
y = i.Years[x+1]
// reset the month
if i.Months != nil {
t = time.Date(t.Year(), i.Months[0], t.Day(), t.Hour(), t.Minute(), t.Second(), 0, t.Location())
}
// reset the monthday
if i.MonthDays != nil {
t = time.Date(t.Year(), t.Month(), i.MonthDays[0], t.Hour(), t.Minute(), t.Second(), 0, t.Location())
}
}
} else { // this year was not found in the list, x is the first greater year
y = i.Years[x]
// reset the month
if i.Months != nil {
t = time.Date(t.Year(), i.Months[0], t.Day(), t.Hour(), t.Minute(), t.Second(), 0, t.Location())
}
// reset the monthday
if i.MonthDays != nil {
t = time.Date(t.Year(), t.Month(), i.MonthDays[0], t.Hour(), t.Minute(), t.Second(), 0, t.Location())
}
}
}
h, min, s := t.Clock()
t = time.Date(y, t.Month(), t.Day(), h, min, s, 0, time.Local)
}
return
}

View File

@@ -225,7 +225,7 @@ func TestActionTimingHourMonthdaysMonths(t *testing.T) {
}
}
func TestActionTimingFisrtOfTheMonth(t *testing.T) {
func TestActionTimingFirstOfTheMonth(t *testing.T) {
now := time.Now()
y, m, _ := now.Date()
nextMonth := time.Date(y, m+1, 1, 0, 0, 0, 0, time.Local)
@@ -241,6 +241,118 @@ func TestActionTimingFisrtOfTheMonth(t *testing.T) {
}
}
func TestActionTimingOnlyYears(t *testing.T) {
now := time.Now()
y, m, d := now.Date()
nextYear := time.Date(y+1, m, d, 0, 0, 0, 0, time.Local)
at := &ActionTiming{Timing: &Interval{Years: Years{now.Year(), nextYear.Year()}}}
st := at.GetNextStartTime()
expected := time.Date(nextYear.Year(), 1, 1, 0, 0, 0, 0, time.Local)
if !st.Equal(expected) {
t.Errorf("Expected %v was %v", expected, st)
}
}
func TestActionTimingHourYears(t *testing.T) {
now := time.Now()
y, m, d := now.Date()
testTime := time.Date(y, m, d, 10, 1, 0, 0, time.Local)
nextYear := time.Date(y+1, m, d, 0, 0, 0, 0, time.Local)
year := now.Year()
if now.After(testTime) {
year = nextYear.Year()
}
at := &ActionTiming{Timing: &Interval{Years: Years{now.Year(), nextYear.Year()}, StartTime: "10:01:00"}}
st := at.GetNextStartTime()
expected := time.Date(year, m, d, 10, 1, 0, 0, time.Local)
if !st.Equal(expected) {
t.Errorf("Expected %v was %v", expected, st)
}
}
func TestActionTimingHourMonthdaysYear(t *testing.T) {
now := time.Now()
y, m, d := now.Date()
testTime := time.Date(y, m, d, 10, 1, 0, 0, time.Local)
nextYear := time.Date(y+1, m, d, 0, 0, 0, 0, time.Local)
tomorrow := time.Date(y, m, d+1, 0, 0, 0, 0, time.Local)
day := now.Day()
if now.After(testTime) {
day = tomorrow.Day()
}
nextDay := time.Date(y, m, day, 10, 1, 0, 0, time.Local)
year := now.Year()
if nextDay.Before(now) {
if now.After(testTime) {
year = nextYear.Year()
}
}
at := &ActionTiming{Timing: &Interval{
Years: Years{now.Year(), nextYear.Year()},
MonthDays: MonthDays{now.Day(), tomorrow.Day()},
StartTime: "10:01:00",
}}
st := at.GetNextStartTime()
expected := time.Date(year, m, day, 10, 1, 0, 0, time.Local)
if !st.Equal(expected) {
t.Errorf("Expected %v was %v", expected, st)
}
}
func TestActionTimingHourMonthdaysMonthYear(t *testing.T) {
now := time.Now()
y, m, d := now.Date()
testTime := time.Date(y, m, d, 10, 1, 0, 0, time.Local)
nextYear := time.Date(y+1, m, d, 0, 0, 0, 0, time.Local)
nextMonth := time.Date(y, m+1, d, 0, 0, 0, 0, time.Local)
tomorrow := time.Date(y, m, d+1, 0, 0, 0, 0, time.Local)
day := now.Day()
if now.After(testTime) {
day = tomorrow.Day()
}
nextDay := time.Date(y, m, day, 10, 1, 0, 0, time.Local)
month := now.Month()
if nextDay.Before(now) {
if now.After(testTime) {
month = nextMonth.Month()
}
}
year := now.Year()
if nextDay.Before(now) {
if now.After(testTime) {
year = nextYear.Year()
}
}
at := &ActionTiming{Timing: &Interval{
Years: Years{now.Year(), nextYear.Year()},
Months: Months{now.Month(), nextMonth.Month()},
MonthDays: MonthDays{now.Day(), tomorrow.Day()},
StartTime: "10:01:00",
}}
st := at.GetNextStartTime()
expected := time.Date(year, month, day, 10, 1, 0, 0, time.Local)
if !st.Equal(expected) {
t.Errorf("Expected %v was %v", expected, st)
}
}
func TestActionTimingFirstOfTheYear(t *testing.T) {
now := time.Now()
y, _, _ := now.Date()
nextYear := time.Date(y+1, 1, 1, 0, 0, 0, 0, time.Local)
at := &ActionTiming{Timing: &Interval{
Years: Years{nextYear.Year()},
Months: Months{time.January},
MonthDays: MonthDays{1},
StartTime: "00:00:00",
}}
st := at.GetNextStartTime()
expected := nextYear
if !st.Equal(expected) {
t.Errorf("Expected %v was %v", expected, st)
}
}
func TestActionTimingIsOneTimeRunNoInterval(t *testing.T) {
at := &ActionTiming{Timing: &Interval{StartTime: ASAP}}
if !at.CheckForASAP() {