mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
new histtory tests
This commit is contained in:
@@ -67,8 +67,8 @@ var (
|
||||
stats = flag.Bool("stats", false, "Generates statsistics about given data.")
|
||||
fromStorDb = flag.Bool("from_stordb", false, "Load the tariff plan from storDb to dataDb")
|
||||
toStorDb = flag.Bool("to_stordb", false, "Import the tariff plan from files to storDb")
|
||||
historyServer = flag.String("history_server", cgrConfig.HistoryServer, "The history server address:port, empty to disable automaticautomatic history archiving")
|
||||
raterAddress = flag.String("rater_address", cgrConfig.MediatorRater, "Rater service to contact for cache reloads, empty to disable automatic cache reloads")
|
||||
historyServer = flag.String("history_server", cgrConfig.RPCGOBListen, "The history server address:port, empty to disable automaticautomatic history archiving")
|
||||
raterAddress = flag.String("rater_address", cgrConfig.RPCGOBListen, "Rater service to contact for cache reloads, empty to disable automatic cache reloads")
|
||||
runId = flag.String("runid", "", "Uniquely identify an import/load, postpended to some automatic fields")
|
||||
)
|
||||
|
||||
@@ -157,8 +157,8 @@ func main() {
|
||||
log.Fatalf("Could not connect to history server, error: %s. Make sure you have properly configured it via -history_server flag.", err.Error())
|
||||
return
|
||||
} else {
|
||||
gob.Register(engine.Destination{})
|
||||
engine.SetHistoryScribe(scribeAgent)
|
||||
gob.Register(&engine.Destination{})
|
||||
defer scribeAgent.Client.Close()
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -96,6 +96,9 @@ func SetDebitPeriod(d time.Duration) {
|
||||
|
||||
// Exported method to set the history scribe.
|
||||
func SetHistoryScribe(scribe history.Scribe) {
|
||||
history.RegisterRecordFilename(&Destination{})
|
||||
history.RegisterRecordFilename(&RatingPlan{})
|
||||
history.RegisterRecordFilename(&RatingProfile{})
|
||||
historyScribe = scribe
|
||||
}
|
||||
|
||||
|
||||
@@ -53,3 +53,8 @@ func (d *Destination) String() (result string) {
|
||||
func (d *Destination) AddPrefix(pfx string) {
|
||||
d.Prefixes = append(d.Prefixes, pfx)
|
||||
}
|
||||
|
||||
// history record method
|
||||
func (d *Destination) GetId() string {
|
||||
return d.Id
|
||||
}
|
||||
|
||||
@@ -27,24 +27,26 @@ import (
|
||||
|
||||
func TestHistoryRatinPlans(t *testing.T) {
|
||||
scribe := historyScribe.(*history.MockScribe)
|
||||
if !strings.Contains(scribe.RpBuf.String(), `{"Key":"*out:vdf:0:minu","Object":{"Id":"*out:vdf:0:minu","RatingPlanActivations":[{"ActivationTime":"2012-01-01T00:00:00Z","RatingPlanId":"EVENING","FallbackKeys":null}]}}`) {
|
||||
t.Error("Error in destination history content:", scribe.RpBuf.String())
|
||||
buf := scribe.BufMap["ratingprofiles.json"]
|
||||
if !strings.Contains(buf.String(), `{"Id":"*out:vdf:0:minu","RatingPlanActivations":[{"ActivationTime":"2012-01-01T00:00:00Z","RatingPlanId":"EVENING","FallbackKeys":null}]}`) {
|
||||
t.Error("Error in destination history content:", buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestHistoryDestinations(t *testing.T) {
|
||||
scribe := historyScribe.(*history.MockScribe)
|
||||
expected := `[{"Key":"ALL","Object":{"Id":"ALL","Prefixes":["49","41","43"]}}
|
||||
{"Key":"GERMANY","Object":{"Id":"GERMANY","Prefixes":["49"]}}
|
||||
{"Key":"GERMANY_O2","Object":{"Id":"GERMANY_O2","Prefixes":["41"]}}
|
||||
{"Key":"GERMANY_PREMIUM","Object":{"Id":"GERMANY_PREMIUM","Prefixes":["43"]}}
|
||||
{"Key":"NAT","Object":{"Id":"NAT","Prefixes":["0256","0257","0723"]}}
|
||||
{"Key":"PSTN_70","Object":{"Id":"PSTN_70","Prefixes":["+4970"]}}
|
||||
{"Key":"PSTN_71","Object":{"Id":"PSTN_71","Prefixes":["+4971"]}}
|
||||
{"Key":"PSTN_72","Object":{"Id":"PSTN_72","Prefixes":["+4972"]}}
|
||||
{"Key":"RET","Object":{"Id":"RET","Prefixes":["0723","0724"]}}
|
||||
{"Key":"nat","Object":{"Id":"nat","Prefixes":["0257","0256","0723"]}}]`
|
||||
if scribe.DestBuf.String() != expected {
|
||||
t.Error("Error in destination history content:", scribe.DestBuf.String())
|
||||
buf := scribe.BufMap["destinations.json"]
|
||||
expected := `[{"Id":"ALL","Prefixes":["49","41","43"]},
|
||||
{"Id":"GERMANY","Prefixes":["49"]},
|
||||
{"Id":"GERMANY_O2","Prefixes":["41"]},
|
||||
{"Id":"GERMANY_PREMIUM","Prefixes":["43"]},
|
||||
{"Id":"NAT","Prefixes":["0256","0257","0723"]},
|
||||
{"Id":"PSTN_70","Prefixes":["+4970"]},
|
||||
{"Id":"PSTN_71","Prefixes":["+4971"]},
|
||||
{"Id":"PSTN_72","Prefixes":["+4972"]},
|
||||
{"Id":"RET","Prefixes":["0723","0724"]},
|
||||
{"Id":"nat","Prefixes":["0257","0256","0723"]}]`
|
||||
if buf.String() != expected {
|
||||
t.Error("Error in destination history content:", buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,3 +97,8 @@ func (rp *RatingPlan) AddRateInterval(dId string, ris ...*RateInterval) {
|
||||
func (rp *RatingPlan) Equal(o *RatingPlan) bool {
|
||||
return rp.Id == o.Id
|
||||
}
|
||||
|
||||
// history record method
|
||||
func (rp *RatingPlan) GetId() string {
|
||||
return rp.Id
|
||||
}
|
||||
|
||||
@@ -146,3 +146,8 @@ func (rp *RatingProfile) GetRatingPlansForPrefix(cd *CallDescriptor) (err error)
|
||||
|
||||
return errors.New("not found")
|
||||
}
|
||||
|
||||
// history record method
|
||||
func (rpf *RatingProfile) GetId() string {
|
||||
return rpf.Id
|
||||
}
|
||||
|
||||
@@ -22,11 +22,10 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/cgrates/cgrates/cache2go"
|
||||
"github.com/cgrates/cgrates/history"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
"strings"
|
||||
"time"
|
||||
"github.com/cgrates/cgrates/cache2go"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
type MapStorage struct {
|
||||
@@ -123,7 +122,7 @@ func (ms *MapStorage) SetRatingPlan(rp *RatingPlan) (err error) {
|
||||
result, err := ms.ms.Marshal(rp)
|
||||
ms.dict[RATING_PLAN_PREFIX+rp.Id] = result
|
||||
response := 0
|
||||
go historyScribe.Record(&history.Record{RATING_PLAN_PREFIX + rp.Id, rp}, &response)
|
||||
go historyScribe.Record(rp, &response)
|
||||
cache2go.Cache(RATING_PLAN_PREFIX+rp.Id, rp)
|
||||
return
|
||||
}
|
||||
@@ -151,7 +150,7 @@ func (ms *MapStorage) SetRatingProfile(rpf *RatingProfile) (err error) {
|
||||
result, err := ms.ms.Marshal(rpf)
|
||||
ms.dict[RATING_PROFILE_PREFIX+rpf.Id] = result
|
||||
response := 0
|
||||
go historyScribe.Record(&history.Record{RATING_PROFILE_PREFIX + rpf.Id, rpf}, &response)
|
||||
go historyScribe.Record(rpf, &response)
|
||||
cache2go.Cache(RATING_PROFILE_PREFIX+rpf.Id, rpf)
|
||||
return
|
||||
}
|
||||
@@ -180,7 +179,7 @@ func (ms *MapStorage) SetDestination(dest *Destination) (err error) {
|
||||
result, err := ms.ms.Marshal(dest)
|
||||
ms.dict[DESTINATION_PREFIX+dest.Id] = result
|
||||
response := 0
|
||||
go historyScribe.Record(&history.Record{DESTINATION_PREFIX + dest.Id, dest}, &response)
|
||||
go historyScribe.Record(dest, &response)
|
||||
cache2go.Cache(DESTINATION_PREFIX+dest.Id, dest)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -20,11 +20,10 @@ package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/cgrates/cgrates/history"
|
||||
"labix.org/v2/mgo"
|
||||
"labix.org/v2/mgo/bson"
|
||||
"log"
|
||||
"time"
|
||||
"labix.org/v2/mgo"
|
||||
"labix.org/v2/mgo/bson"
|
||||
)
|
||||
|
||||
type MongoStorage struct {
|
||||
@@ -137,7 +136,7 @@ func (ms *MongoStorage) GetRatingPlan(key string) (rp *RatingPlan, err error) {
|
||||
func (ms *MongoStorage) SetRatingPlan(rp *RatingPlan) error {
|
||||
if historyScribe != nil {
|
||||
response := 0
|
||||
historyScribe.Record(&history.Record{RATING_PLAN_PREFIX + rp.Id, rp}, &response)
|
||||
historyScribe.Record(rp, &response)
|
||||
}
|
||||
return ms.db.C("ratingplans").Insert(rp)
|
||||
}
|
||||
@@ -151,7 +150,7 @@ func (ms *MongoStorage) GetRatingProfile(key string) (rp *RatingProfile, err err
|
||||
func (ms *MongoStorage) SetRatingProfile(rp *RatingProfile) error {
|
||||
if historyScribe != nil {
|
||||
response := 0
|
||||
historyScribe.Record(&history.Record{RATING_PROFILE_PREFIX + rp.Id, rp}, &response)
|
||||
historyScribe.Record(rp, &response)
|
||||
}
|
||||
return ms.db.C("ratingprofiles").Insert(rp)
|
||||
}
|
||||
@@ -168,7 +167,7 @@ func (ms *MongoStorage) GetDestination(key string) (result *Destination, err err
|
||||
func (ms *MongoStorage) SetDestination(dest *Destination) error {
|
||||
if historyScribe != nil {
|
||||
response := 0
|
||||
historyScribe.Record(&history.Record{DESTINATION_PREFIX + dest.Id, dest}, &response)
|
||||
historyScribe.Record(dest, &response)
|
||||
}
|
||||
return ms.db.C("destinations").Insert(dest)
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cgrates/cgrates/cache2go"
|
||||
"github.com/cgrates/cgrates/history"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
"github.com/hoisie/redis"
|
||||
|
||||
@@ -195,7 +194,7 @@ func (rs *RedisStorage) SetRatingPlan(rp *RatingPlan) (err error) {
|
||||
err = rs.db.Set(RATING_PLAN_PREFIX+rp.Id, b.Bytes())
|
||||
if err == nil && historyScribe != nil {
|
||||
response := 0
|
||||
go historyScribe.Record(&history.Record{RATING_PLAN_PREFIX + rp.Id, rp}, &response)
|
||||
go historyScribe.Record(rp, &response)
|
||||
}
|
||||
//cache2go.Cache(RATING_PLAN_PREFIX+rp.Id, rp)
|
||||
return
|
||||
@@ -223,7 +222,7 @@ func (rs *RedisStorage) SetRatingProfile(rpf *RatingProfile) (err error) {
|
||||
err = rs.db.Set(RATING_PROFILE_PREFIX+rpf.Id, result)
|
||||
if err == nil && historyScribe != nil {
|
||||
response := 0
|
||||
go historyScribe.Record(&history.Record{RATING_PROFILE_PREFIX + rpf.Id, rpf}, &response)
|
||||
go historyScribe.Record(rpf, &response)
|
||||
}
|
||||
//cache2go.Cache(RATING_PROFILE_PREFIX+rpf.Id, rpf)
|
||||
return
|
||||
@@ -272,7 +271,7 @@ func (rs *RedisStorage) SetDestination(dest *Destination) (err error) {
|
||||
err = rs.db.Set(DESTINATION_PREFIX+dest.Id, b.Bytes())
|
||||
if err == nil && historyScribe != nil {
|
||||
response := 0
|
||||
go historyScribe.Record(&history.Record{DESTINATION_PREFIX + dest.Id, dest}, &response)
|
||||
go historyScribe.Record(dest, &response)
|
||||
}
|
||||
//cache2go.Cache(DESTINATION_PREFIX+dest.Id, dest)
|
||||
return
|
||||
|
||||
@@ -22,31 +22,22 @@ import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
DESTINATIONS_FILE = "destinations.json"
|
||||
RATING_PLANS_FILE = "rating_plans.json"
|
||||
RATING_PROFILES_FILE = "rating_profiles.json"
|
||||
)
|
||||
|
||||
type FileScribe struct {
|
||||
mu sync.Mutex
|
||||
fileRoot string
|
||||
gitCommand string
|
||||
destinations records
|
||||
ratingPlans records
|
||||
ratingProfiles records
|
||||
loopChecker chan int
|
||||
waitingFile string
|
||||
savePeriod time.Duration
|
||||
mu sync.Mutex
|
||||
fileRoot string
|
||||
gitCommand string
|
||||
loopChecker chan int
|
||||
waitingFile string
|
||||
savePeriod time.Duration
|
||||
}
|
||||
|
||||
func NewFileScribe(fileRoot string, saveInterval time.Duration) (*FileScribe, error) {
|
||||
@@ -58,31 +49,20 @@ func NewFileScribe(fileRoot string, saveInterval time.Duration) (*FileScribe, er
|
||||
s := &FileScribe{fileRoot: fileRoot, gitCommand: gitCommand, savePeriod: saveInterval}
|
||||
s.loopChecker = make(chan int)
|
||||
s.gitInit()
|
||||
if err := s.load(DESTINATIONS_FILE); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := s.load(RATING_PLANS_FILE); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := s.load(RATING_PROFILES_FILE); err != nil {
|
||||
return nil, err
|
||||
|
||||
for fn, _ := range recordsMap {
|
||||
if err := s.load(fn); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *FileScribe) Record(rec *Record, out *int) error {
|
||||
func (s *FileScribe) Record(rec Record, out *int) error {
|
||||
s.mu.Lock()
|
||||
var fileToSave string
|
||||
switch {
|
||||
case strings.HasPrefix(rec.Key, DESTINATION_PREFIX):
|
||||
s.destinations = s.destinations.SetOrAdd(&Record{rec.Key[len(DESTINATION_PREFIX):], rec.Object})
|
||||
fileToSave = DESTINATIONS_FILE
|
||||
case strings.HasPrefix(rec.Key, RATING_PLAN_PREFIX):
|
||||
s.ratingPlans = s.ratingPlans.SetOrAdd(&Record{rec.Key[len(RATING_PLAN_PREFIX):], rec.Object})
|
||||
fileToSave = RATING_PLANS_FILE
|
||||
case strings.HasPrefix(rec.Key, RATING_PROFILE_PREFIX):
|
||||
s.ratingProfiles = s.ratingProfiles.SetOrAdd(&Record{rec.Key[len(RATING_PROFILE_PREFIX):], rec.Object})
|
||||
fileToSave = RATING_PROFILES_FILE
|
||||
fileToSave := GetRFN(rec)
|
||||
if records, ok := recordsMap[fileToSave]; ok {
|
||||
records.SetOrAdd(rec)
|
||||
}
|
||||
|
||||
// flood protection for save method (do not save on every loop iteration)
|
||||
@@ -126,21 +106,14 @@ func (s *FileScribe) gitInit() error {
|
||||
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 errors.New("<History> Error writing destinations file: " + err.Error())
|
||||
} else {
|
||||
f.Close()
|
||||
}
|
||||
if f, err := os.Create(filepath.Join(s.fileRoot, RATING_PLANS_FILE)); err != nil {
|
||||
return errors.New("<History> Error writing rating plans file: " + err.Error())
|
||||
} else {
|
||||
f.Close()
|
||||
}
|
||||
if f, err := os.Create(filepath.Join(s.fileRoot, RATING_PROFILES_FILE)); err != nil {
|
||||
return errors.New("<History> Error writing rating profiles file: " + err.Error())
|
||||
} else {
|
||||
f.Close()
|
||||
for fn, _ := range recordsMap {
|
||||
if f, err := os.Create(filepath.Join(s.fileRoot, fn)); err != nil {
|
||||
return fmt.Errorf("<History> Error writing %s file: %s", fn, err.Error())
|
||||
} else {
|
||||
f.Close()
|
||||
}
|
||||
}
|
||||
|
||||
cmd = exec.Command(s.gitCommand, "add", ".")
|
||||
cmd.Dir = s.fileRoot
|
||||
if out, err := cmd.Output(); err != nil {
|
||||
@@ -169,23 +142,11 @@ func (s *FileScribe) load(filename string) error {
|
||||
defer f.Close()
|
||||
d := json.NewDecoder(f)
|
||||
|
||||
switch filename {
|
||||
case DESTINATIONS_FILE:
|
||||
if err := d.Decode(&s.destinations); err != nil && err != io.EOF {
|
||||
return errors.New("<History> Error loading destinations: " + err.Error())
|
||||
}
|
||||
s.destinations.Sort()
|
||||
case RATING_PLANS_FILE:
|
||||
if err := d.Decode(&s.ratingPlans); err != nil && err != io.EOF {
|
||||
return errors.New("<History> Error loading rating plans: " + err.Error())
|
||||
}
|
||||
s.ratingPlans.Sort()
|
||||
case RATING_PROFILES_FILE:
|
||||
if err := d.Decode(&s.ratingProfiles); err != nil && err != io.EOF {
|
||||
return errors.New("<History> Error loading rating profiles: " + err.Error())
|
||||
}
|
||||
s.ratingProfiles.Sort()
|
||||
records := recordsMap[filename]
|
||||
if err := d.Decode(&records); err != nil && err != io.EOF {
|
||||
return fmt.Errorf("<History> Error loading %s: %s", filename, err.Error())
|
||||
}
|
||||
records.Sort()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -198,38 +159,11 @@ func (s *FileScribe) save(filename string) error {
|
||||
}
|
||||
|
||||
b := bufio.NewWriter(f)
|
||||
switch filename {
|
||||
case DESTINATIONS_FILE:
|
||||
if err := s.format(b, s.destinations); err != nil {
|
||||
return err
|
||||
}
|
||||
case RATING_PLANS_FILE:
|
||||
if err := s.format(b, s.ratingPlans); err != nil {
|
||||
return err
|
||||
}
|
||||
case RATING_PROFILES_FILE:
|
||||
if err := s.format(b, s.ratingProfiles); err != nil {
|
||||
return err
|
||||
}
|
||||
records := recordsMap[filename]
|
||||
if err := format(b, records); err != nil {
|
||||
return err
|
||||
}
|
||||
b.Flush()
|
||||
f.Close()
|
||||
return s.gitCommit()
|
||||
}
|
||||
|
||||
func (s *FileScribe) format(b io.Writer, recs records) error {
|
||||
recs.Sort()
|
||||
b.Write([]byte("["))
|
||||
for i, r := range recs {
|
||||
src, err := json.Marshal(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.Write(src)
|
||||
if i < len(recs)-1 {
|
||||
b.Write([]byte(",\n"))
|
||||
}
|
||||
}
|
||||
b.Write([]byte("]"))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -21,85 +21,38 @@ package history
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type MockScribe struct {
|
||||
mu sync.Mutex
|
||||
destinations records
|
||||
ratingPlans records
|
||||
ratingProfiles records
|
||||
DestBuf bytes.Buffer
|
||||
RplBuf bytes.Buffer
|
||||
RpBuf bytes.Buffer
|
||||
mu sync.Mutex
|
||||
BufMap map[string]*bytes.Buffer
|
||||
}
|
||||
|
||||
func NewMockScribe() (*MockScribe, error) {
|
||||
return &MockScribe{}, nil
|
||||
return &MockScribe{BufMap: map[string]*bytes.Buffer{
|
||||
"destinations.json": bytes.NewBuffer(nil),
|
||||
"ratingplans.json": bytes.NewBuffer(nil),
|
||||
"ratingprofiles.json": bytes.NewBuffer(nil),
|
||||
}}, nil
|
||||
}
|
||||
|
||||
func (s *MockScribe) Record(rec *Record, out *int) error {
|
||||
switch {
|
||||
case strings.HasPrefix(rec.Key, DESTINATION_PREFIX):
|
||||
s.destinations = s.destinations.SetOrAdd(&Record{rec.Key[len(DESTINATION_PREFIX):], rec.Object})
|
||||
s.save(DESTINATIONS_FILE)
|
||||
case strings.HasPrefix(rec.Key, RATING_PLAN_PREFIX):
|
||||
s.ratingPlans = s.ratingPlans.SetOrAdd(&Record{rec.Key[len(RATING_PLAN_PREFIX):], rec.Object})
|
||||
s.save(RATING_PLANS_FILE)
|
||||
case strings.HasPrefix(rec.Key, RATING_PROFILE_PREFIX):
|
||||
s.ratingProfiles = s.ratingProfiles.SetOrAdd(&Record{rec.Key[len(RATING_PROFILE_PREFIX):], rec.Object})
|
||||
s.save(RATING_PROFILES_FILE)
|
||||
}
|
||||
*out = 0
|
||||
func (s *MockScribe) Record(rec Record, out *int) error {
|
||||
fn := GetRFN(rec)
|
||||
recordsMap[fn] = recordsMap[fn].SetOrAdd(rec)
|
||||
s.save(fn)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *MockScribe) save(filename string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
switch filename {
|
||||
case 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 RATING_PLANS_FILE:
|
||||
s.RplBuf.Reset()
|
||||
b := bufio.NewWriter(&s.RplBuf)
|
||||
defer b.Flush()
|
||||
if err := s.format(b, s.ratingPlans); err != nil {
|
||||
return err
|
||||
}
|
||||
case 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
|
||||
}
|
||||
records := recordsMap[filename]
|
||||
s.BufMap[filename].Reset()
|
||||
b := bufio.NewWriter(s.BufMap[filename])
|
||||
defer b.Flush()
|
||||
if err := format(b, records); 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 recs {
|
||||
src, err := json.Marshal(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.Write(src)
|
||||
if i < len(recs)-1 {
|
||||
b.Write([]byte("\n"))
|
||||
}
|
||||
}
|
||||
b.Write([]byte("]"))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -18,11 +18,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
|
||||
package history
|
||||
|
||||
import "net/rpc"
|
||||
|
||||
const (
|
||||
JSON = "json"
|
||||
GOB = "gob"
|
||||
import (
|
||||
"encoding/gob"
|
||||
"log"
|
||||
"net/rpc"
|
||||
)
|
||||
|
||||
type ProxyScribe struct {
|
||||
@@ -38,6 +37,12 @@ func NewProxyScribe(addr string) (*ProxyScribe, error) {
|
||||
return &ProxyScribe{Client: client}, nil
|
||||
}
|
||||
|
||||
func (ps *ProxyScribe) Record(rec *Record, out *int) error {
|
||||
return ps.Client.Call("Scribe.Record", rec, out)
|
||||
func RRR(r interface{}) {
|
||||
gob.Register(r)
|
||||
}
|
||||
|
||||
func (ps *ProxyScribe) Record(rec Record, out *int) error {
|
||||
err := ps.Client.Call("Scribe.Record", &rec, out)
|
||||
log.Printf("Result for %v: %v", rec, err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -19,25 +19,27 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
package history
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"reflect"
|
||||
"sort"
|
||||
)
|
||||
|
||||
const (
|
||||
RATING_PLAN_PREFIX = "rpl_"
|
||||
RATING_PROFILE_PREFIX = "rpf_"
|
||||
DESTINATION_PREFIX = "dst_"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Scribe interface {
|
||||
Record(record *Record, out *int) error
|
||||
Record(Record, *int) error
|
||||
}
|
||||
|
||||
type Record struct {
|
||||
Key string
|
||||
Object interface{}
|
||||
type Record interface {
|
||||
GetId() string
|
||||
}
|
||||
|
||||
type records []*Record
|
||||
type records []Record
|
||||
|
||||
var (
|
||||
recordsMap = make(map[string]records)
|
||||
filenameMap = make(map[reflect.Type]string)
|
||||
)
|
||||
|
||||
func (rs records) Len() int {
|
||||
return len(rs)
|
||||
@@ -48,19 +50,19 @@ func (rs records) Swap(i, j int) {
|
||||
}
|
||||
|
||||
func (rs records) Less(i, j int) bool {
|
||||
return rs[i].Key < rs[j].Key
|
||||
return rs[i].GetId() < rs[j].GetId()
|
||||
}
|
||||
|
||||
func (rs records) Sort() {
|
||||
sort.Sort(rs)
|
||||
}
|
||||
|
||||
func (rs records) SetOrAdd(rec *Record) records {
|
||||
func (rs records) SetOrAdd(rec Record) records {
|
||||
//rs.Sort()
|
||||
n := len(rs)
|
||||
i := sort.Search(n, func(i int) bool { return rs[i].Key >= rec.Key })
|
||||
if i < n && rs[i].Key == rec.Key {
|
||||
rs[i].Object = rec.Object
|
||||
i := sort.Search(n, func(i int) bool { return rs[i].GetId() >= rec.GetId() })
|
||||
if i < n && rs[i].GetId() == rec.GetId() {
|
||||
rs[i] = rec
|
||||
} else {
|
||||
// i is the index where it would be inserted.
|
||||
rs = append(rs, nil)
|
||||
@@ -70,10 +72,10 @@ func (rs records) SetOrAdd(rec *Record) records {
|
||||
return rs
|
||||
}
|
||||
|
||||
func (rs records) SetOrAddOld(rec *Record) records {
|
||||
/*func (rs records) SetOrAdd(rec Record) records {
|
||||
found := false
|
||||
for _, r := range rs {
|
||||
if r.Key == rec.Key {
|
||||
if r.GetId() == rec.GetId() {
|
||||
found = true
|
||||
r.Object = rec.Object
|
||||
return rs
|
||||
@@ -83,4 +85,36 @@ func (rs records) SetOrAddOld(rec *Record) records {
|
||||
rs = append(rs, rec)
|
||||
}
|
||||
return rs
|
||||
}*/
|
||||
|
||||
func format(b io.Writer, recs records) error {
|
||||
recs.Sort()
|
||||
b.Write([]byte("["))
|
||||
for i, r := range recs {
|
||||
src, err := json.Marshal(r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b.Write(src)
|
||||
if i < len(recs)-1 {
|
||||
b.Write([]byte(",\n"))
|
||||
}
|
||||
}
|
||||
b.Write([]byte("]"))
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetRFN(rec Record) string {
|
||||
if fn, ok := filenameMap[reflect.TypeOf(rec)]; ok {
|
||||
return fn
|
||||
} else {
|
||||
typ := reflect.TypeOf(rec)
|
||||
typeSegments := strings.Split(typ.String(), ".")
|
||||
fn = strings.ToLower(typeSegments[len(typeSegments)-1]) + "s.json"
|
||||
filenameMap[typ] = fn
|
||||
recordsMap[fn] = make(records, 0)
|
||||
return fn
|
||||
}
|
||||
}
|
||||
|
||||
var RegisterRecordFilename = GetRFN // will create a key in filename and records map
|
||||
|
||||
@@ -23,18 +23,28 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
type TestRecord struct {
|
||||
Id string
|
||||
}
|
||||
|
||||
func (tr *TestRecord) GetId() string {
|
||||
return tr.Id
|
||||
}
|
||||
|
||||
func TestHistorySet(t *testing.T) {
|
||||
rs := records{&Record{"first", "test"}}
|
||||
rs.SetOrAdd(&Record{"first", "new value"})
|
||||
if len(rs) != 1 || rs[0].Object != "new value" {
|
||||
rs := records{&TestRecord{"first"}}
|
||||
second := &TestRecord{"first"}
|
||||
rs.SetOrAdd(second)
|
||||
if len(rs) != 1 || rs[0] != second {
|
||||
t.Error("error setting new value: ", rs[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestHistoryAdd(t *testing.T) {
|
||||
rs := records{&Record{"first", "test"}}
|
||||
rs = rs.SetOrAdd(&Record{"second", "new value"})
|
||||
if len(rs) != 2 || rs[1].Object != "new value" {
|
||||
rs := records{&TestRecord{"first"}}
|
||||
second := &TestRecord{"second"}
|
||||
rs = rs.SetOrAdd(second)
|
||||
if len(rs) != 2 || rs[1] != second {
|
||||
t.Error("error setting new value: ", rs)
|
||||
}
|
||||
}
|
||||
@@ -42,19 +52,9 @@ func TestHistoryAdd(t *testing.T) {
|
||||
func BenchmarkSetOrAdd(b *testing.B) {
|
||||
var rs records
|
||||
for i := 0; i < 1000; i++ {
|
||||
rs = rs.SetOrAdd(&Record{strconv.Itoa(i), strconv.Itoa(i)})
|
||||
rs = rs.SetOrAdd(&TestRecord{strconv.Itoa(i)})
|
||||
}
|
||||
for i := 0; i < b.N; i++ {
|
||||
rs.SetOrAdd(&Record{"400", "test"})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSetOrAddOld(b *testing.B) {
|
||||
var rs records
|
||||
for i := 0; i < 1000; i++ {
|
||||
rs = rs.SetOrAddOld(&Record{strconv.Itoa(i), strconv.Itoa(i)})
|
||||
}
|
||||
for i := 0; i < b.N; i++ {
|
||||
rs.SetOrAddOld(&Record{"400", "test"})
|
||||
rs.SetOrAdd(&TestRecord{"400"})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user