diff --git a/cmd/loader/loader.go b/cmd/loader/loader.go index 06f027e22..06c7b6dc3 100644 --- a/cmd/loader/loader.go +++ b/cmd/loader/loader.go @@ -16,21 +16,31 @@ var ( mongoserver = flag.String("mongoserver", "127.0.0.1:27017", "mongo server address (127.0.0.1:27017)") mongodb = flag.String("mdb", "test", "mongo database name (test)") redispass = flag.String("pass", "", "redis database password") - inputfile = flag.String("inputfile", "input.json", "redis database password") + apfile = flag.String("apfile", "ap.json", "Activation Periods containing intervals file") + destfile = flag.String("destfile", "dest.json", "Destinations file") ) +func writeToStorage(storage timespans.StorageGetter,callDescriptors []*timespans.CallDescriptor,destinations []*timespans.Destination){ + for _, cd := range callDescriptors { + storage.SetActivationPeriods(cd.GetKey(), cd.ActivationPeriods) + log.Printf("Storing %q", cd.GetKey()) + } + for _, d := range destinations { + storage.SetDestination(d) + log.Printf("Storing %q", d.Id) + } +} + func main() { flag.Parse() - log.Printf("Reading from %q", *inputfile) - fin, err := os.Open(*inputfile) - defer fin.Close() + log.Print("Reading from ", *apfile, *destfile) - if err != nil { - log.Print("Cannot open input file", err) - return - } + // reading activation periods + fin, err := os.Open(*apfile) + + if err != nil {log.Print("Cannot open activation periods input file", err)} dec := json.NewDecoder(fin) @@ -39,29 +49,35 @@ func main() { log.Println(err) return } + fin.Close() + + // reading destinations + fin, err = os.Open(*destfile) + + if err != nil {log.Print("Cannot open destinations input file", err)} + + dec = json.NewDecoder(fin) + + var destinations []*timespans.Destination + if err := dec.Decode(&destinations); err != nil { + log.Println(err) + return + } + fin.Close() switch *storage { case "kyoto": storage, _ := timespans.NewKyotoStorage(*kyotofile) defer storage.Close() - for _, cd := range callDescriptors { - storage.SetActivationPeriods(cd.GetKey(), cd.ActivationPeriods) - log.Printf("Storing %q", cd.GetKey()) - } + writeToStorage(storage, callDescriptors, destinations) case "mongo": storage, _ := timespans.NewMongoStorage("127.0.0.1", "test") defer storage.Close() - for _, cd := range callDescriptors { - storage.SetActivationPeriods(cd.GetKey(), cd.ActivationPeriods) - log.Printf("Storing %q", cd.GetKey()) - } + writeToStorage(storage, callDescriptors, destinations) default: storage, _ := timespans.NewRedisStorage(*redisserver, *redisdb) defer storage.Close() - for _, cd := range callDescriptors { - storage.SetActivationPeriods(cd.GetKey(), cd.ActivationPeriods) - log.Printf("Storing %q", cd.GetKey()) - } + writeToStorage(storage, callDescriptors, destinations) } } diff --git a/timespans/activationperiod.go b/timespans/activationperiod.go index 89b972b6b..7ba6d40dd 100644 --- a/timespans/activationperiod.go +++ b/timespans/activationperiod.go @@ -1,8 +1,8 @@ package timespans import ( - "strings" "strconv" + "strings" "time" //"log" ) diff --git a/timespans/calldesc.go b/timespans/calldesc.go index ec69dd2d6..b65bfa789 100644 --- a/timespans/calldesc.go +++ b/timespans/calldesc.go @@ -161,7 +161,7 @@ func (cd *CallDescriptor) getPresentSecondCost(sg StorageGetter) (cost float64, ts := &TimeSpan{TimeStart: now, TimeEnd: now.Add(oneSecond)} timespans := cd.splitTimeSpan(ts) - if len(timespans)>0 { + if len(timespans) > 0 { cost = round(timespans[0].GetCost(), 3) } return diff --git a/timespans/destinations.go b/timespans/destinations.go new file mode 100644 index 000000000..4535b5302 --- /dev/null +++ b/timespans/destinations.go @@ -0,0 +1,26 @@ +package timespans + +import ( + "strings" +) + +type Destination struct { + Id string + Prefixes []string +} + +func (d *Destination) GetKey() (result string) { + return d.Id +} + +func (d *Destination) store() (result string) { + for _, p := range d.Prefixes { + result += p + "," + } + result = strings.TrimRight(result, ",") + return +} + +func (d *Destination) restore(input string) { + d.Prefixes = strings.Split(input, ",") +} diff --git a/timespans/destinations_test.go b/timespans/destinations_test.go new file mode 100644 index 000000000..6893cc0dd --- /dev/null +++ b/timespans/destinations_test.go @@ -0,0 +1,80 @@ +package timespans + +import ( + "testing" +) + +func TestDestinationStoreRestore(t *testing.T){ + nationale = &Destination{Id: "nat", Prefixes: []string{"0257", "0256", "0723"}} + s := nationale.store() + d1 := &Destination{Id: "nationale"} + d1.restore(s) + if d1.store() != s { + t.Errorf("Expected %q was %q", s, d1.store()) + } +} + +func TestKyotoStore(t *testing.T){ + getter, _ := NewKyotoStorage("test.kch") + defer getter.Close() + nationale = &Destination{Id: "nat", Prefixes: []string{"0257", "0256", "0723"}} + getter.SetDestination(nationale) + result, _ := getter.GetDestination(nationale.Id) + if result.Id != nationale.Id || result.Prefixes[2] != nationale.Prefixes[2] { + t.Errorf("Expected %q was %q", nationale, result) + } +} + +func TestRedisStore(t *testing.T){ + getter, _ := NewRedisStorage("tcp:127.0.0.1:6379", 10) + defer getter.Close() + nationale = &Destination{Id: "nat", Prefixes: []string{"0257", "0256", "0723"}} + getter.SetDestination(nationale) + result, _ := getter.GetDestination(nationale.Id) + if result.Id != nationale.Id || result.Prefixes[2] != nationale.Prefixes[2] { + t.Errorf("Expected %q was %q", nationale, result) + } +} + +func TestMongoStore(t *testing.T){ + getter, _ := NewMongoStorage("127.0.0.1", "test") + defer getter.Close() + nationale = &Destination{Id: "nat", Prefixes: []string{"0257", "0256", "0723"}} + getter.SetDestination(nationale) + result, _ := getter.GetDestination(nationale.Id) + if result.Id != nationale.Id || result.Prefixes[2] != nationale.Prefixes[2] { + t.Errorf("Expected %q was %q", nationale, result) + } +} + +/********************************* Benchmarks **********************************/ + +func BenchmarkDestinationKyotoStoreRestore(b *testing.B){ + getter, _ := NewKyotoStorage("test.kch") + defer getter.Close() + nationale = &Destination{Id: "nat", Prefixes: []string{"0257", "0256", "0723"}} + for i := 0; i < b.N; i++ { + getter.SetDestination(nationale) + getter.GetDestination(nationale.Id) + } +} + +func BenchmarkDestinationRedisStoreRestore(b *testing.B){ + getter, _ := NewRedisStorage("tcp:127.0.0.1:6379", 10) + defer getter.Close() + nationale = &Destination{Id: "nat", Prefixes: []string{"0257", "0256", "0723"}} + for i := 0; i < b.N; i++ { + getter.SetDestination(nationale) + getter.GetDestination(nationale.Id) + } +} + +func BenchmarkDestinationMongoStoreRestore(b *testing.B){ + getter, _ := NewMongoStorage("127.0.0.1", "test") + defer getter.Close() + nationale = &Destination{Id: "nat", Prefixes: []string{"0257", "0256", "0723"}} + for i := 0; i < b.N; i++ { + getter.SetDestination(nationale) + getter.GetDestination(nationale.Id) + } +} diff --git a/timespans/kyoto_storage.go b/timespans/kyoto_storage.go index a8990e4db..e4f87e3c1 100644 --- a/timespans/kyoto_storage.go +++ b/timespans/kyoto_storage.go @@ -1,8 +1,8 @@ package timespans import ( - "strings" "github.com/fsouza/gokabinet/kc" + "strings" ) type KyotoStorage struct { @@ -10,7 +10,7 @@ type KyotoStorage struct { } func NewKyotoStorage(filaName string) (*KyotoStorage, error) { - ndb, err := kc.Open(filaName, kc.READ) + ndb, err := kc.Open(filaName, kc.WRITE) return &KyotoStorage{db: ndb}, err } @@ -23,20 +23,31 @@ func (ks *KyotoStorage) GetActivationPeriods(key string) (aps []*ActivationPerio if err == nil { for _, ap_string := range strings.Split(values, "\n") { - if len(ap_string) > 0 { - ap := &ActivationPeriod{} - ap.restore(ap_string) - aps = append(aps, ap) - } + if len(ap_string) > 0 { + ap := &ActivationPeriod{} + ap.restore(ap_string) + aps = append(aps, ap) + } } } return aps, err } -func (ks *KyotoStorage) SetActivationPeriods(key string, aps []*ActivationPeriod){ +func (ks *KyotoStorage) SetActivationPeriods(key string, aps []*ActivationPeriod) { result := "" for _, ap := range aps { result += ap.store() + "\n" } ks.db.Set(key, result) } + +func (ks *KyotoStorage) GetDestination(key string) (dest *Destination, err error) { + values, err := ks.db.Get(key) + dest = &Destination{Id:key} + dest.restore(values) + return +} + +func (ks *KyotoStorage) SetDestination(dest *Destination) { + ks.db.Set(dest.Id, dest.store()) +} diff --git a/timespans/mongo_storage.go b/timespans/mongo_storage.go index 79e027b60..212a24837 100644 --- a/timespans/mongo_storage.go +++ b/timespans/mongo_storage.go @@ -6,12 +6,12 @@ import ( ) type KeyValue struct { - Key string + Key string ActivationPeriods []*ActivationPeriod } type MongoStorage struct { - db *mgo.Collection + db *mgo.Database session *mgo.Session } @@ -22,8 +22,12 @@ func NewMongoStorage(address, db string) (*MongoStorage, error) { } session.SetMode(mgo.Monotonic, true) - ndb := session.DB(db).C("ap") - return &MongoStorage{db: ndb, session: session}, nil + index := mgo.Index{Key: []string{"key"},Unique: true,DropDups: true,Background: true} + err = session.DB(db).C("ap").EnsureIndex(index) + index = mgo.Index{Key: []string{"id"},Unique: true,DropDups: true,Background: true} + err = session.DB(db).C("dest").EnsureIndex(index) + + return &MongoStorage{db: session.DB(db), session: session}, nil } func (ms *MongoStorage) Close() { @@ -31,11 +35,25 @@ func (ms *MongoStorage) Close() { } func (ms *MongoStorage) GetActivationPeriods(key string) (aps []*ActivationPeriod, err error) { + ndb := ms.db.C("ap") result := KeyValue{} - err = ms.db.Find(bson.M{"key": key}).One(&result) + err = ndb.Find(bson.M{"key": key}).One(&result) return result.ActivationPeriods, err } -func (ms *MongoStorage) SetActivationPeriods(key string, aps []*ActivationPeriod){ - ms.db.Insert(&KeyValue{key, aps}) +func (ms *MongoStorage) SetActivationPeriods(key string, aps []*ActivationPeriod) { + ndb := ms.db.C("ap") + ndb.Insert(&KeyValue{key, aps}) +} + +func (ms *MongoStorage) GetDestination(key string) (result *Destination, err error) { + ndb := ms.db.C("dest") + result = &Destination{} + err = ndb.Find(bson.M{"id": key}).One(result) + return +} + +func (ms *MongoStorage) SetDestination(dest *Destination) { + ndb := ms.db.C("dest") + ndb.Insert(&dest) } diff --git a/timespans/redis_storage.go b/timespans/redis_storage.go index 1350b36c8..6ad10261e 100644 --- a/timespans/redis_storage.go +++ b/timespans/redis_storage.go @@ -1,8 +1,8 @@ package timespans import ( - "strings" "github.com/simonz05/godis" + "strings" ) type RedisStorage struct { @@ -20,23 +20,34 @@ func (rs *RedisStorage) Close() { func (rs *RedisStorage) GetActivationPeriods(key string) (aps []*ActivationPeriod, err error) { elem, err := rs.db.Get(key) - values:= elem.String() + values := elem.String() if err == nil { for _, ap_string := range strings.Split(values, "\n") { - if len(ap_string) > 0 { - ap := &ActivationPeriod{} - ap.restore(ap_string) - aps = append(aps, ap) - } + if len(ap_string) > 0 { + ap := &ActivationPeriod{} + ap.restore(ap_string) + aps = append(aps, ap) + } } } return aps, err } -func (rs *RedisStorage) SetActivationPeriods(key string, aps []*ActivationPeriod){ +func (rs *RedisStorage) SetActivationPeriods(key string, aps []*ActivationPeriod) { result := "" for _, ap := range aps { result += ap.store() + "\n" } rs.db.Set(key, result) } + +func (rs *RedisStorage) GetDestination(key string) (dest *Destination, err error) { + values, err := rs.db.Get(key) + dest = &Destination{Id:key} + dest.restore(values.String()) + return +} + +func (rs *RedisStorage) SetDestination(dest *Destination) { + rs.db.Set(dest.Id, dest.store()) +} diff --git a/timespans/storage_interface.go b/timespans/storage_interface.go index 3f8c8d659..35bed1a77 100644 --- a/timespans/storage_interface.go +++ b/timespans/storage_interface.go @@ -7,4 +7,6 @@ type StorageGetter interface { Close() GetActivationPeriods(key string) ([]*ActivationPeriod, error) SetActivationPeriods(key string, aps []*ActivationPeriod) + GetDestination(key string) (*Destination, error) + SetDestination(dest *Destination) } diff --git a/timespans/test.kch b/timespans/test.kch index cf1a25715..47d449be9 100644 Binary files a/timespans/test.kch and b/timespans/test.kch differ diff --git a/timespans/test_destinations.json b/timespans/test_destinations.json index 0bb54b11c..5e9948506 100644 --- a/timespans/test_destinations.json +++ b/timespans/test_destinations.json @@ -1,3 +1,5 @@ -{"Id":"nationale", "Prefixes":["0256","0257","0723","0740"]} -{"Id":"mobil", "Prefixes":["0723","0740"]} +[ +{"Id":"nationale", "Prefixes":["0256","0257","0723","0740"]}, +{"Id":"mobil", "Prefixes":["0723","0740"]}, {"Id":"radu", "Prefixes":["0723045326"]} +] diff --git a/timespans/userbudget.go b/timespans/userbudget.go index 55665ec31..d1e436fdd 100644 --- a/timespans/userbudget.go +++ b/timespans/userbudget.go @@ -39,26 +39,6 @@ func (ub *UserBudget) GetSecondsForPrefix(prefix string) (seconds int) { return } -type Destination struct { - Id string - Prefixes []string -} - -func (d *Destination) GetKey() (result string) { - return d.Id -} - -func (d *Destination) store() (result string) { - for _, p := range d.Prefixes { - result += p + "," - } - return -} - -func (d *Destination) restore(input string) { - d.Prefixes := strings.Split(input, ",") -} - type MinuteBucket struct { seconds int priority int @@ -67,7 +47,7 @@ type MinuteBucket struct { } func (mb *MinuteBucket) containsPrefix(prefix string) bool { - for _, p := range mb.destination.prefixes { + for _, p := range mb.destination.Prefixes { if prefix == p { return true } diff --git a/timespans/userbudget_test.go b/timespans/userbudget_test.go index 381b460ae..21e3f092d 100644 --- a/timespans/userbudget_test.go +++ b/timespans/userbudget_test.go @@ -5,8 +5,8 @@ import ( ) var ( - nationale = &Destination{id: "nationale", prefixes: []string{"0257", "0256", "0723"}} - retea = &Destination{id: "retea", prefixes: []string{"0723", "0724"}} + nationale = &Destination{Id: "nationale", Prefixes: []string{"0257", "0256", "0723"}} + retea = &Destination{Id: "retea", Prefixes: []string{"0723", "0724"}} ) func TestGetSeconds(t *testing.T) {