added rating profile history handler

This commit is contained in:
Radu Ioan Fericean
2013-08-02 18:57:46 +03:00
parent 10f46f348a
commit 8c8f003239
7 changed files with 157 additions and 50 deletions

File diff suppressed because one or more lines are too long

View File

@@ -55,6 +55,7 @@ func (ms *MapStorage) GetRatingProfile(key string) (rp *RatingProfile, err error
func (ms *MapStorage) SetRatingProfile(rp *RatingProfile) (err error) {
result, err := ms.ms.Marshal(rp)
ms.dict[RATING_PROFILE_PREFIX+rp.Id] = result
go historyScribe.Record(RATING_PROFILE_PREFIX+rp.Id, rp)
return
}
@@ -70,7 +71,7 @@ func (ms *MapStorage) GetDestination(key string) (dest *Destination, err error)
func (ms *MapStorage) SetDestination(dest *Destination) (err error) {
result, err := ms.ms.Marshal(dest)
ms.dict[DESTINATION_PREFIX+dest.Id] = result
historyScribe.Record(dest.Id, dest)
go historyScribe.Record(DESTINATION_PREFIX+dest.Id, dest)
return
}

View File

@@ -21,9 +21,8 @@ package engine
import (
"errors"
"fmt"
"menteslibres.net/gosexy/redis"
//"log"
"github.com/cgrates/cgrates/utils"
"menteslibres.net/gosexy/redis"
"strconv"
"strings"
"time"

View File

@@ -25,80 +25,145 @@ import (
"io"
"os"
"os/exec"
"path/filepath"
"strings"
"sync"
)
const (
DESTINATIONS_FILE = "destinations.json"
RATING_PROFILES_FILE = "rating_profiles.json"
)
type FileScribe struct {
sync.RWMutex
filename string
records records
fileRoot string
gitCommand string
destinations records
ratingProfiles records
}
func NewFileScribe(filename string) (Scribe, error) {
func NewFileScribe(fileRoot string) (Scribe, error) {
// looking for git
_, err := exec.LookPath("git")
gitCommand, err := exec.LookPath("git")
if err != nil {
return nil, errors.New("Please install git: " + err.Error())
}
s := &FileScribe{filename: filename}
return s, s.load()
s := &FileScribe{fileRoot: fileRoot, gitCommand: gitCommand}
s.gitInit()
if err := s.load(DESTINATIONS_FILE); err != nil {
return nil, err
}
if err := s.load(RATING_PROFILES_FILE); err != nil {
return nil, err
}
return s, nil
}
func (s *FileScribe) Record(key string, obj interface{}) error {
s.Lock()
defer s.Unlock()
s.records = s.records.SetOrAdd(key, obj)
s.save()
switch {
case strings.HasPrefix(key, DESTINATION_PREFIX):
s.destinations = s.destinations.SetOrAdd(key, obj)
s.save(DESTINATIONS_FILE)
case strings.HasPrefix(key, RATING_PROFILE_PREFIX):
s.ratingProfiles = s.ratingProfiles.SetOrAdd(key, obj)
s.save(RATING_PROFILES_FILE)
}
return nil
}
func (s *FileScribe) commit() error {
out, err := exec.Command("git", "commit", "-a", "-m", "'historic commit'").Output()
if err != nil {
func (s *FileScribe) gitInit() error {
if _, err := os.Stat(filepath.Join(s.fileRoot, ".git")); os.IsNotExist(err) {
cmd := exec.Command(s.gitCommand, "init")
cmd.Dir = s.fileRoot
if out, err := cmd.Output(); err != nil {
return errors.New(string(out) + " " + err.Error())
}
if f, err := os.Create(filepath.Join(s.fileRoot, DESTINATIONS_FILE)); err != nil {
return err
} else {
f.Close()
}
if f, err := os.Create(filepath.Join(s.fileRoot, RATING_PROFILES_FILE)); err != nil {
return err
} else {
f.Close()
}
cmd = exec.Command(s.gitCommand, "add")
cmd.Dir = s.fileRoot
if out, err := cmd.Output(); err != nil {
return errors.New(string(out) + " " + err.Error())
}
}
return nil
}
func (s *FileScribe) gitCommit() error {
cmd := exec.Command(s.gitCommand, "commit", "-a", "-m", "'historic commit'")
cmd.Dir = s.fileRoot
if out, err := cmd.Output(); err != nil {
return errors.New(string(out) + " " + err.Error())
}
return nil
}
func (s *FileScribe) load() error {
f, err := os.Open(s.filename)
func (s *FileScribe) load(filename string) error {
f, err := os.Open(filepath.Join(s.fileRoot, filename))
if err != nil {
return err
}
defer f.Close()
d := json.NewDecoder(f)
if err := d.Decode(&s.records); err != nil {
return err
switch {
case filename == DESTINATIONS_FILE:
if err := d.Decode(&s.destinations); err != nil {
return err
}
s.destinations.Sort()
case filename == RATING_PROFILES_FILE:
if err := d.Decode(&s.ratingProfiles); err != nil {
return err
}
s.ratingProfiles.Sort()
}
s.records.Sort()
return nil
}
func (s *FileScribe) save() error {
f, err := os.Create(s.filename)
func (s *FileScribe) save(filename string) error {
f, err := os.Create(filepath.Join(s.fileRoot, filename))
if err != nil {
return err
}
b := bufio.NewWriter(f)
defer b.Flush()
if err := s.format(b); err != nil {
return err
switch {
case filename == DESTINATIONS_FILE:
if err := s.format(b, s.destinations); err != nil {
return err
}
case filename == RATING_PROFILES_FILE:
if err := s.format(b, s.ratingProfiles); err != nil {
return err
}
}
return s.commit()
return s.gitCommit()
}
func (s *FileScribe) format(b io.Writer) error {
s.records.Sort()
func (s *FileScribe) format(b io.Writer, recs records) error {
recs.Sort()
b.Write([]byte("["))
for i, r := range s.records {
for i, r := range recs {
src, err := json.Marshal(r)
if err != nil {
return err
}
b.Write(src)
if i < len(s.records)-1 {
if i < len(recs)-1 {
b.Write([]byte("\n"))
}
}

View File

@@ -23,13 +23,16 @@ import (
"bytes"
"encoding/json"
"io"
"strings"
"sync"
)
type MockScribe struct {
sync.RWMutex
records records
Buf bytes.Buffer
destinations records
ratingProfiles records
DestBuf bytes.Buffer
RpBuf bytes.Buffer
}
func NewMockScribe() (Scribe, error) {
@@ -39,31 +42,48 @@ func NewMockScribe() (Scribe, error) {
func (s *MockScribe) Record(key string, obj interface{}) error {
s.Lock()
defer s.Unlock()
s.records = s.records.SetOrAdd(key, obj)
s.save()
return nil
}
func (s *MockScribe) save() error {
s.Buf.Reset()
b := bufio.NewWriter(&s.Buf)
defer b.Flush()
if err := s.format(b); err != nil {
return err
switch {
case strings.HasPrefix(key, DESTINATION_PREFIX):
s.destinations = s.destinations.SetOrAdd(key[len(DESTINATION_PREFIX):], obj)
s.save(DESTINATIONS_FILE)
case strings.HasPrefix(key, RATING_PROFILE_PREFIX):
s.ratingProfiles = s.ratingProfiles.SetOrAdd(key[len(DESTINATION_PREFIX):], obj)
s.save(RATING_PROFILES_FILE)
}
return nil
}
func (s *MockScribe) format(b io.Writer) error {
s.records.Sort()
func (s *MockScribe) save(filename string) error {
switch {
case filename == DESTINATIONS_FILE:
s.DestBuf.Reset()
b := bufio.NewWriter(&s.DestBuf)
defer b.Flush()
if err := s.format(b, s.destinations); err != nil {
return err
}
case filename == RATING_PROFILES_FILE:
s.RpBuf.Reset()
b := bufio.NewWriter(&s.RpBuf)
defer b.Flush()
if err := s.format(b, s.ratingProfiles); err != nil {
return err
}
}
return nil
}
func (s *MockScribe) format(b io.Writer, recs records) error {
recs.Sort()
b.Write([]byte("["))
for i, r := range s.records {
for i, r := range recs {
src, err := json.Marshal(r)
if err != nil {
return err
}
b.Write(src)
if i < len(s.records)-1 {
if i < len(recs)-1 {
b.Write([]byte("\n"))
}
}

View File

@@ -22,6 +22,11 @@ import (
"sort"
)
const (
RATING_PROFILE_PREFIX = "rpf_"
DESTINATION_PREFIX = "dst_"
)
type Scribe interface {
Record(key string, obj interface{}) error
}

View File

@@ -97,10 +97,11 @@ func Round(x float64, prec int, method string) float64 {
}
func ParseDate(date string) (expDate time.Time, err error) {
date = strings.TrimSpace(date)
switch {
case date == "*unlimited" || date == "":
// leave it at zero
case string(date[0]) == "+":
case strings.HasPrefix(date, "+"):
d, err := time.ParseDuration(date[1:])
if err != nil {
return expDate, err
@@ -108,7 +109,7 @@ func ParseDate(date string) (expDate time.Time, err error) {
expDate = time.Now().Add(d)
case date == "*monthly":
expDate = time.Now().AddDate(0, 1, 0) // add one month
case strings.Contains(date, "Z"):
case strings.HasSuffix(date, "Z"):
expDate, err = time.Parse(time.RFC3339, date)
default:
unix, err := strconv.ParseInt(date, 10, 64)