diff --git a/balancer2go/balancer.go b/balancer2go/balancer.go deleted file mode 100644 index a97fa06e8..000000000 --- a/balancer2go/balancer.go +++ /dev/null @@ -1,104 +0,0 @@ -/* -Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments -Copyright (C) ITsysCOM GmbH - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ -package balancer2go - -import ( - "sync" -) - -// The main balancer type -type Balancer struct { - sync.RWMutex - clients map[string]Worker - balancerChannel chan Worker -} - -// Interface for RPC clients -type Worker interface { - Call(serviceMethod string, args interface{}, reply interface{}) error - Close() error -} - -// Constructor for RateList holding one slice for addreses and one slice for connections. -func NewBalancer() *Balancer { - r := &Balancer{clients: make(map[string]Worker), balancerChannel: make(chan Worker)} // leaving both slices to nil - go func() { - for { - if len(r.clients) > 0 { - for _, c := range r.clients { - r.balancerChannel <- c - } - } else { - r.balancerChannel <- nil - } - } - }() - return r -} - -// Adds a client to the two internal map. -func (bl *Balancer) AddClient(address string, client Worker) { - bl.Lock() - defer bl.Unlock() - bl.clients[address] = client - return -} - -// Removes a client from the map locking the readers and reseting the balancer index. -func (bl *Balancer) RemoveClient(address string) { - bl.Lock() - defer bl.Unlock() - delete(bl.clients, address) - <-bl.balancerChannel -} - -// Returns a client for the specifed address. -func (bl *Balancer) GetClient(address string) (c Worker, exists bool) { - bl.RLock() - defer bl.RUnlock() - c, exists = bl.clients[address] - return -} - -// Returns the next available connection at each call looping at the end of connections. -func (bl *Balancer) Balance() (result Worker) { - bl.RLock() - defer bl.RUnlock() - return <-bl.balancerChannel -} - -// Sends a shotdown call to the clients -func (bl *Balancer) Shutdown(shutdownMethod string) { - bl.Lock() - defer bl.Unlock() - var reply string - for _, client := range bl.clients { - client.Call(shutdownMethod, "", &reply) - } -} - -// Returns a string slice with all client addresses -func (bl *Balancer) GetClientAddresses() []string { - bl.RLock() - defer bl.RUnlock() - var addresses []string - for a, _ := range bl.clients { - addresses = append(addresses, a) - } - return addresses -} diff --git a/balancer2go/balancer_test.go b/balancer2go/balancer_test.go deleted file mode 100644 index 7c8856a67..000000000 --- a/balancer2go/balancer_test.go +++ /dev/null @@ -1,69 +0,0 @@ -/* -Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments -Copyright (C) ITsysCOM GmbH - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see -*/ -package balancer2go - -import ( - "net/rpc" - "testing" -) - -func BenchmarkBalance(b *testing.B) { - balancer := NewBalancer() - balancer.AddClient("client 1", new(rpc.Client)) - balancer.AddClient("client 2", new(rpc.Client)) - balancer.AddClient("client 3", new(rpc.Client)) - for i := 0; i < b.N; i++ { - balancer.Balance() - } -} - -func TestRemoving(t *testing.T) { - balancer := NewBalancer() - c1 := new(rpc.Client) - c2 := new(rpc.Client) - c3 := new(rpc.Client) - balancer.AddClient("client 1", c1) - balancer.AddClient("client 2", c2) - balancer.AddClient("client 3", c3) - balancer.RemoveClient("client 2") - if balancer.clients["client 1"] != c1 || - balancer.clients["client 3"] != c3 || - len(balancer.clients) != 2 { - t.Error("Failed removing rater") - } -} - -func TestGet(t *testing.T) { - balancer := NewBalancer() - c1 := new(rpc.Client) - balancer.AddClient("client 1", c1) - result, ok := balancer.GetClient("client 1") - if !ok || c1 != result { - t.Error("Get failed") - } -} - -func TestOneBalancer(t *testing.T) { - balancer := NewBalancer() - balancer.AddClient("client 1", new(rpc.Client)) - c1 := balancer.Balance() - c2 := balancer.Balance() - if c1 != c2 { - t.Error("With only one rater these shoud be equal") - } -} diff --git a/cmd/cgr-engine/cgr-engine.go b/cmd/cgr-engine/cgr-engine.go index 47b392a57..a971acec1 100644 --- a/cmd/cgr-engine/cgr-engine.go +++ b/cmd/cgr-engine/cgr-engine.go @@ -32,7 +32,6 @@ import ( "github.com/cgrates/cgrates/agents" "github.com/cgrates/cgrates/apier/v1" "github.com/cgrates/cgrates/apier/v2" - "github.com/cgrates/cgrates/balancer2go" "github.com/cgrates/cgrates/cache" "github.com/cgrates/cgrates/cdrc" "github.com/cgrates/cgrates/config" @@ -657,7 +656,6 @@ func main() { // Async starts here, will follow cgrates.json start order // Define internal connections via channels - internalBalancerChan := make(chan *balancer2go.Balancer, 1) internalRaterChan := make(chan rpcclient.RpcClientConnection, 1) cacheDoneChan := make(chan struct{}, 1) internalCdrSChan := make(chan rpcclient.RpcClientConnection, 1) @@ -672,14 +670,9 @@ func main() { // Start ServiceManager srvManager := servmanager.NewServiceManager(cfg, dataDB, exitChan, cacheDoneChan) - // Start balancer service - if cfg.BalancerEnabled { - go startBalancer(internalBalancerChan, &stopHandled, exitChan) // Not really needed async here but to cope with uniformity - } - // Start rater service if cfg.RALsEnabled { - go startRater(internalRaterChan, cacheDoneChan, internalBalancerChan, internalCdrStatSChan, internalHistorySChan, internalPubSubSChan, internalUserSChan, internalAliaseSChan, + go startRater(internalRaterChan, cacheDoneChan, internalCdrStatSChan, internalHistorySChan, internalPubSubSChan, internalUserSChan, internalAliaseSChan, srvManager, server, dataDB, loadDb, cdrDb, &stopHandled, exitChan) } diff --git a/cmd/cgr-engine/engine_test.go b/cmd/cgr-engine/engine_test.go index 12a028088..3f95d3930 100644 --- a/cmd/cgr-engine/engine_test.go +++ b/cmd/cgr-engine/engine_test.go @@ -22,20 +22,6 @@ import ( "testing" ) -/*func TestRPCGet(t *testing.T) { - client, err := rpc.DialHTTPPath("tcp", "localhost:2000", "/rpc") - if err != nil { - t.Error("Balancer server not started!") - t.FailNow() - } - var reply string - client.Call("Responder.Get", "test", &reply) - const expect = "12223" - if reply != expect { - t.Errorf("replay == %v, want %v", reply, expect) - } -}*/ - func BenchmarkRPCGet(b *testing.B) { b.StopTimer() client, _ := rpc.DialHTTPPath("tcp", "localhost:2000", "/rpc") diff --git a/cmd/cgr-engine/rater.go b/cmd/cgr-engine/rater.go index bd85d6207..1719cb971 100644 --- a/cmd/cgr-engine/rater.go +++ b/cmd/cgr-engine/rater.go @@ -19,11 +19,9 @@ package main import ( "fmt" - "time" "github.com/cgrates/cgrates/apier/v1" "github.com/cgrates/cgrates/apier/v2" - "github.com/cgrates/cgrates/balancer2go" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/history" "github.com/cgrates/cgrates/servmanager" @@ -42,15 +40,8 @@ import ( gob.Register(engine.AliasValues{}) }*/ -func startBalancer(internalBalancerChan chan *balancer2go.Balancer, stopHandled *bool, exitChan chan bool) { - bal := balancer2go.NewBalancer() - go stopBalancerSignalHandler(bal, exitChan) - *stopHandled = true - internalBalancerChan <- bal -} - // Starts rater and reports on chan -func startRater(internalRaterChan chan rpcclient.RpcClientConnection, cacheDoneChan chan struct{}, internalBalancerChan chan *balancer2go.Balancer, +func startRater(internalRaterChan chan rpcclient.RpcClientConnection, cacheDoneChan chan struct{}, internalCdrStatSChan chan rpcclient.RpcClientConnection, internalHistorySChan chan rpcclient.RpcClientConnection, internalPubSubSChan chan rpcclient.RpcClientConnection, internalUserSChan chan rpcclient.RpcClientConnection, internalAliaseSChan chan rpcclient.RpcClientConnection, serviceManager *servmanager.ServiceManager, server *utils.Server, @@ -127,28 +118,6 @@ func startRater(internalRaterChan chan rpcclient.RpcClientConnection, cacheDoneC cacheDoneChan <- struct{}{} }() - var bal *balancer2go.Balancer - if cfg.RALsBalancer != "" { // Connection to balancer - balTaskChan := make(chan struct{}) - waitTasks = append(waitTasks, balTaskChan) - go func() { - defer close(balTaskChan) - if cfg.RALsBalancer == utils.MetaInternal { - select { - case bal = <-internalBalancerChan: - internalBalancerChan <- bal // Put it back if someone else is interested about - case <-time.After(cfg.InternalTtl): - utils.Logger.Crit(": Internal balancer connection timeout.") - exitChan <- true - return - } - } else { - go registerToBalancer(exitChan) - go stopRaterSignalHandler(internalCdrStatSChan, exitChan) - *stopHandled = true - } - }() - } var cdrStats *rpcclient.RpcClientPool if len(cfg.RALsCDRStatSConns) != 0 { // Connections to CDRStats cdrstatTaskChan := make(chan struct{}) @@ -228,7 +197,7 @@ func startRater(internalRaterChan chan rpcclient.RpcClientConnection, cacheDoneC for _, chn := range waitTasks { <-chn } - responder := &engine.Responder{Bal: bal, ExitChan: exitChan} + responder := &engine.Responder{ExitChan: exitChan} responder.SetTimeToLive(cfg.ResponseCacheTTL, nil) apierRpcV1 := &v1.ApierV1{StorDb: loadDb, DataDB: dataDB, CdrDb: cdrDb, Config: cfg, Responder: responder, ServManager: serviceManager, HTTPPoster: utils.NewHTTPPoster(cfg.HttpSkipTlsVerify, cfg.ReplyTimeout)} diff --git a/cmd/cgr-engine/registration.go b/cmd/cgr-engine/registration.go index 3e0dd48fb..22f8ef7c7 100644 --- a/cmd/cgr-engine/registration.go +++ b/cmd/cgr-engine/registration.go @@ -19,38 +19,23 @@ package main import ( "fmt" - "net/rpc" "os" "os/signal" "syscall" - "github.com/cgrates/cgrates/balancer2go" "github.com/cgrates/cgrates/utils" "github.com/cgrates/rpcclient" ) /* -Listens for SIGTERM, SIGINT, SIGQUIT system signals and shuts down all the registered engines. -*/ -func stopBalancerSignalHandler(bal *balancer2go.Balancer, exitChan chan bool) { - c := make(chan os.Signal) - signal.Notify(c, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT) - sig := <-c - utils.Logger.Info(fmt.Sprintf("Caught signal %v, sending shutdown to engines\n", sig)) - bal.Shutdown("Responder.Shutdown") - exitChan <- true -} - -/* -Listens for the SIGTERM, SIGINT, SIGQUIT system signals and gracefuly unregister from balancer and closes the storage before exiting. +Listens for the SIGTERM, SIGINT, SIGQUIT system signals and closes the storage before exiting. */ func stopRaterSignalHandler(internalCdrStatSChan chan rpcclient.RpcClientConnection, exitChan chan bool) { c := make(chan os.Signal) signal.Notify(c, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT) sig := <-c - utils.Logger.Info(fmt.Sprintf("Caught signal %v, unregistering from balancer\n", sig)) - unregisterFromBalancer(exitChan) + utils.Logger.Info(fmt.Sprintf("Caught signal %v", sig)) var dummyInt int select { case cdrStats := <-internalCdrStatSChan: @@ -60,45 +45,6 @@ func stopRaterSignalHandler(internalCdrStatSChan chan rpcclient.RpcClientConnect exitChan <- true } -/* -Connects to the balancer and calls unregister RPC method. -*/ -func unregisterFromBalancer(exitChan chan bool) { - client, err := rpc.Dial("tcp", cfg.RALsBalancer) - if err != nil { - utils.Logger.Crit("Cannot contact the balancer!") - exitChan <- true - return - } - var reply int - utils.Logger.Info(fmt.Sprintf("Unregistering from balancer %s", cfg.RALsBalancer)) - client.Call("Responder.UnRegisterRater", cfg.RPCGOBListen, &reply) - if err := client.Close(); err != nil { - utils.Logger.Crit("Could not close balancer unregistration!") - exitChan <- true - } -} - -/* -Connects to the balancer and rehisters the engine to the server. -*/ -func registerToBalancer(exitChan chan bool) { - client, err := rpc.Dial("tcp", cfg.RALsBalancer) - if err != nil { - utils.Logger.Crit(fmt.Sprintf("Cannot contact the balancer: %v", err)) - exitChan <- true - return - } - var reply int - utils.Logger.Info(fmt.Sprintf("Registering to balancer %s", cfg.RALsBalancer)) - client.Call("Responder.RegisterRater", cfg.RPCGOBListen, &reply) - if err := client.Close(); err != nil { - utils.Logger.Crit("Could not close balancer registration!") - exitChan <- true - } - utils.Logger.Info("Registration finished!") -} - /* Listens for the SIGTERM, SIGINT, SIGQUIT system signals and shuts down the session manager. */ diff --git a/config/config.go b/config/config.go index 5236bc5d1..27f570c21 100644 --- a/config/config.go +++ b/config/config.go @@ -220,7 +220,6 @@ type CGRConfig struct { LockingTimeout time.Duration // locking mechanism timeout to avoid deadlocks LogLevel int // system wide log level, nothing higher than this will be logged RALsEnabled bool // start standalone server (no balancer) - RALsBalancer string // balancer address host:port RALsCDRStatSConns []*HaPoolConfig // address where to reach the cdrstats service. Empty to disable stats gathering <""|internal|x.y.z.y:1234> RALsHistorySConns []*HaPoolConfig RALsPubSubSConns []*HaPoolConfig @@ -228,7 +227,6 @@ type CGRConfig struct { RALsAliasSConns []*HaPoolConfig RpSubjectPrefixMatching bool // enables prefix matching for the rating profile subject LcrSubjectPrefixMatching bool // enables prefix matching for the lcr subject - BalancerEnabled bool SchedulerEnabled bool CDRSEnabled bool // Enable CDR Server service CDRSExtraFields []*utils.RSRField // Extra fields to store in CDRs @@ -274,9 +272,6 @@ type CGRConfig struct { func (self *CGRConfig) checkConfigSanity() error { // Rater checks if self.RALsEnabled { - if self.RALsBalancer == utils.MetaInternal && !self.BalancerEnabled { - return errors.New("Balancer not enabled but requested by Rater component.") - } for _, connCfg := range self.RALsCDRStatSConns { if connCfg.Address == utils.MetaInternal && !self.CDRStatsEnabled { return errors.New("CDRStats not enabled but requested by Rater component.") @@ -520,11 +515,6 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) error { return err } - jsnBalancerCfg, err := jsnCfg.BalancerJsonCfg() - if err != nil { - return err - } - jsnRALsCfg, err := jsnCfg.RalsJsonCfg() if err != nil { return err @@ -781,9 +771,6 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) error { if jsnRALsCfg.Enabled != nil { self.RALsEnabled = *jsnRALsCfg.Enabled } - if jsnRALsCfg.Balancer != nil { - self.RALsBalancer = *jsnRALsCfg.Balancer - } if jsnRALsCfg.Cdrstats_conns != nil { self.RALsCDRStatSConns = make([]*HaPoolConfig, len(*jsnRALsCfg.Cdrstats_conns)) for idx, jsnHaCfg := range *jsnRALsCfg.Cdrstats_conns { @@ -826,15 +813,9 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) error { self.LcrSubjectPrefixMatching = *jsnRALsCfg.Lcr_subject_prefix_matching } } - - if jsnBalancerCfg != nil && jsnBalancerCfg.Enabled != nil { - self.BalancerEnabled = *jsnBalancerCfg.Enabled - } - if jsnSchedCfg != nil && jsnSchedCfg.Enabled != nil { self.SchedulerEnabled = *jsnSchedCfg.Enabled } - if jsnCdrsCfg != nil { if jsnCdrsCfg.Enabled != nil { self.CDRSEnabled = *jsnCdrsCfg.Enabled diff --git a/config/config_defaults.go b/config/config_defaults.go index 8c8402935..6b2f8b067 100644 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -106,15 +106,8 @@ const CGRATES_CFG_JSON = ` "cdrs_indexes": [], // indexes on cdrs table to speed up queries, used only in case of mongo }, - -"balancer": { - "enabled": false, // start Balancer service: -}, - - "rals": { "enabled": false, // enable Rater service: - "balancer": "", // register to balancer as worker: <""|*internal|x.y.z.y:1234> "cdrstats_conns": [], // address where to reach the cdrstats service, empty to disable stats functionality: <""|*internal|x.y.z.y:1234> "historys_conns": [], // address where to reach the history service, empty to disable history functionality: <""|*internal|x.y.z.y:1234> "pubsubs_conns": [], // address where to reach the pubusb service, empty to disable pubsub functionality: <""|*internal|x.y.z.y:1234> diff --git a/config/config_json.go b/config/config_json.go index 2b66d5906..31067faca 100644 --- a/config/config_json.go +++ b/config/config_json.go @@ -32,7 +32,6 @@ const ( HTTP_JSN = "http" DATADB_JSN = "data_db" STORDB_JSN = "stor_db" - BALANCER_JSN = "balancer" RALS_JSN = "rals" SCHEDULER_JSN = "scheduler" CDRS_JSN = "cdrs" @@ -142,18 +141,6 @@ func (self CgrJsonCfg) DbJsonCfg(section string) (*DbJsonCfg, error) { return cfg, nil } -func (self CgrJsonCfg) BalancerJsonCfg() (*BalancerJsonCfg, error) { - rawCfg, hasKey := self[BALANCER_JSN] - if !hasKey { - return nil, nil - } - cfg := new(BalancerJsonCfg) - if err := json.Unmarshal(*rawCfg, cfg); err != nil { - return nil, err - } - return cfg, nil -} - func (self CgrJsonCfg) RalsJsonCfg() (*RalsJsonCfg, error) { rawCfg, hasKey := self[RALS_JSN] if !hasKey { diff --git a/config/config_json_test.go b/config/config_json_test.go index c904dde51..20583273d 100644 --- a/config/config_json_test.go +++ b/config/config_json_test.go @@ -150,17 +150,8 @@ func TestDfDbJsonCfg(t *testing.T) { } } -func TestDfBalancerJsonCfg(t *testing.T) { - eCfg := &BalancerJsonCfg{Enabled: utils.BoolPointer(false)} - if cfg, err := dfCgrJsonCfg.BalancerJsonCfg(); err != nil { - t.Error(err) - } else if !reflect.DeepEqual(eCfg, cfg) { - t.Error("Received: ", cfg) - } -} - func TestDfRalsJsonCfg(t *testing.T) { - eCfg := &RalsJsonCfg{Enabled: utils.BoolPointer(false), Balancer: utils.StringPointer(""), Cdrstats_conns: &[]*HaPoolJsonCfg{}, + eCfg := &RalsJsonCfg{Enabled: utils.BoolPointer(false), Cdrstats_conns: &[]*HaPoolJsonCfg{}, Historys_conns: &[]*HaPoolJsonCfg{}, Pubsubs_conns: &[]*HaPoolJsonCfg{}, Users_conns: &[]*HaPoolJsonCfg{}, Aliases_conns: &[]*HaPoolJsonCfg{}, Rp_subject_prefix_matching: utils.BoolPointer(false), Lcr_subject_prefix_matching: utils.BoolPointer(false)} if cfg, err := dfCgrJsonCfg.RalsJsonCfg(); err != nil { diff --git a/config/config_test.go b/config/config_test.go index 4a66d5068..19f311994 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -262,12 +262,6 @@ func TestCgrCfgJSONDefaultsStorDB(t *testing.T) { } } -func TestCgrCfgJSONDefaultsBalancer(t *testing.T) { - if cgrCfg.BalancerEnabled != false { - t.Error(cgrCfg.BalancerEnabled) - } -} - func TestCgrCfgJSONDefaultsRALs(t *testing.T) { eHaPoolcfg := []*HaPoolConfig{} @@ -275,9 +269,6 @@ func TestCgrCfgJSONDefaultsRALs(t *testing.T) { if cgrCfg.RALsEnabled != false { t.Error(cgrCfg.RALsEnabled) } - if cgrCfg.RALsBalancer != "" { - t.Error(cgrCfg.RALsBalancer) - } if !reflect.DeepEqual(cgrCfg.RALsCDRStatSConns, eHaPoolcfg) { t.Error(cgrCfg.RALsCDRStatSConns) } diff --git a/config/libconfig_json.go b/config/libconfig_json.go index e2d88d541..11f990151 100644 --- a/config/libconfig_json.go +++ b/config/libconfig_json.go @@ -69,15 +69,9 @@ type DbJsonCfg struct { Cdrs_indexes *[]string } -// Balancer config section -type BalancerJsonCfg struct { - Enabled *bool -} - // Rater config section type RalsJsonCfg struct { Enabled *bool - Balancer *string Cdrstats_conns *[]*HaPoolJsonCfg Historys_conns *[]*HaPoolJsonCfg Pubsubs_conns *[]*HaPoolJsonCfg diff --git a/data/conf/cgrates/cgrates.json b/data/conf/cgrates/cgrates.json index 6963edfc1..1e3f6c51a 100644 --- a/data/conf/cgrates/cgrates.json +++ b/data/conf/cgrates/cgrates.json @@ -87,14 +87,8 @@ // }, -// "balancer": { -// "enabled": false, // start Balancer service: -// }, - - // "rals": { // "enabled": false, // enable Rater service: -// "balancer": "", // register to balancer as worker: <""|*internal|x.y.z.y:1234> // "cdrstats_conns": [], // address where to reach the cdrstats service, empty to disable stats functionality: <""|*internal|x.y.z.y:1234> // "historys_conns": [], // address where to reach the history service, empty to disable history functionality: <""|*internal|x.y.z.y:1234> // "pubsubs_conns": [], // address where to reach the pubusb service, empty to disable pubsub functionality: <""|*internal|x.y.z.y:1234> diff --git a/docs/administration.rst b/docs/administration.rst index 17b258dfa..8e07efb81 100644 --- a/docs/administration.rst +++ b/docs/administration.rst @@ -5,7 +5,7 @@ The general steps to get CGRateS operational are: #. Create CSV files containing the initial data for CGRateS. #. Load the data in the databases using the Loader application. -#. Start the a Balancer or a Rater. If Balancer is used, start one or more Raters serving that Balancer. -#. Start the SessionManager talking to your VoIP Switch or directly make API calls to the Balancer/Rater. -#. Make API calls to the Balancer/Rater or just let the SessionManager do the work. +#. Start a Rater. +#. Start the SessionManager talking to your VoIP Switch or directly make API calls to the Rater. +#. Make API calls to the Rater or just let the SessionManager do the work. diff --git a/docs/apicalls.rst b/docs/apicalls.rst index fc0577fde..684a68ce1 100644 --- a/docs/apicalls.rst +++ b/docs/apicalls.rst @@ -1,6 +1,6 @@ API Calls ========= -The general API usage of the CGRateS involves creating a CallDescriptor structure sending it to the balancer via JSON/GOB RPC and getting a response from the balancer in form of a CallCost structure or a numeric value for requested information. +The general API usage of the CGRateS involves creating a CallDescriptor structure sending it to the rater via JSON/GOB RPC and getting a response from the rater in form of a CallCost structure or a numeric value for requested information. CallDescriptor structure ------------------------ @@ -48,11 +48,11 @@ Cost ConnectFee The requested connection cost Timespans - The timespans in witch the initial TimeStart-TimeEnd was split in for cost determination with all pricing and cost information attached. + The timespans in witch the initial TimeStart-TimeEnd was split in for cost determination with all pricing and cost information attached. -As stated before the balancer (or the rater directly) can be accesed via json rpc. +As stated before the rater can be accesed via json rpc. -The smallest python snippet to access the CGRateS balancer is this: +The smallest python snippet to access the CGRateS rater is this: :: @@ -76,7 +76,7 @@ In the stress folder you can find a better example of python client using a clas rpc =JSONClient(("127.0.0.1", 2001)) result = rpc.call("Responder.Get", cd) print result - + Call API -------- GetCost @@ -102,7 +102,7 @@ DebitSeconds The amount filed has to be filled in call descriptor. GetMaxSessionTime - Returns the approximate max allowed session for user budget. It will try the max amount received in the call descriptor + Returns the approximate max allowed session for user budget. It will try the max amount received in the call descriptor and will decrease it by 10% for nine times. So if the user has little credit it will still allow 10% of the initial amount. If the user has no credit then it will return 0. @@ -336,7 +336,7 @@ SetAcount Type string // <*prepaid|*postpaid> ActionTimingsId string } - + Example AddAccount(attr \*AttrAddAccount, reply \*string) diff --git a/docs/architecture.rst b/docs/architecture.rst index 26f093f1b..2ede51816 100644 --- a/docs/architecture.rst +++ b/docs/architecture.rst @@ -72,24 +72,7 @@ it will start on demand **one or more** service(s), outlined below. .. hint:: # cgr-engine -config_dir=/etc/cgrates -2.1.1. Balancer service -~~~~~~~~~~~~~~~~~~~~~~~ -*Optional* component, used as proxy/balancer to a pool of RAL workers. -The RALs will register their availability to the Balancer thus implementing **dynamic HA functionality**. -**HA functionality** can be archived also *without* the **Balancer**. - -- Communicates via: - - RPC - - internal/in-process *within the same running* **cgr-engine** process. - -- Operates with the following CGRateS database(s): :: - - - none - -- Config section in the CGRateS configuration file: - - ``"balancer": {...}`` - -2.1.2. RALs service +2.1.1. RALs service ~~~~~~~~~~~~~~~~~~~~ Responsible with the following tasks: @@ -110,7 +93,7 @@ Responsible with the following tasks: - Config section in the CGRateS configuration file: - ``"rals": {...}`` -2.1.3. Scheduler service +2.1.2. Scheduler service ~~~~~~~~~~~~~~~~~~~~~~~~ Used to execute periodic/scheduled tasks. @@ -124,7 +107,7 @@ Used to execute periodic/scheduled tasks. - Config section in the CGRateS configuration file: - ``"scheduler": {...}`` -2.1.4. SessionManager service +2.1.3. SessionManager service ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Responsible with call control on the Telecommunication Switch side. Operates in two different modes (per call or globally): @@ -164,7 +147,7 @@ Right now there are **five** session manager types. - ``"sm_asterisk": {...}`` - ``"sm_generic": {...}`` -2.1.5. DiameterAgent service +2.1.4. DiameterAgent service ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Responsible for the communication with Diameter server via diameter protocol. Despite the name it is a flexible **Diameter Server**. @@ -180,7 +163,7 @@ Despite the name it is a flexible **Diameter Server**. - Config section in the CGRateS configuration file: - ``"diameter_agent": {...}`` -2.1.6. CDRS service +2.1.5. CDRS service ~~~~~~~~~~~~~~~~~~~ Centralized CDR server and CDR (raw or rated) **replicator**. @@ -196,7 +179,7 @@ Centralized CDR server and CDR (raw or rated) **replicator**. - Config section in the CGRateS configuration file: - ``"cdrs": {...}`` -2.1.7. CDRStats service +2.1.6. CDRStats service ~~~~~~~~~~~~~~~~~~~~~~~ Computes real-time CDR stats. Capable with real-time fraud detection and mitigation with actions triggered. @@ -211,7 +194,7 @@ Computes real-time CDR stats. Capable with real-time fraud detection and mitigat - Config section in the CGRateS configuration file: - ``"cdrstats": {...}`` -2.1.8. CDRC service +2.1.7. CDRC service ~~~~~~~~~~~~~~~~~~~ Gathers offline CDRs and post them to CDR Server - (CDRS component) @@ -226,7 +209,7 @@ Gathers offline CDRs and post them to CDR Server - (CDRS component) - Config section in the CGRateS configuration file: - ``"cdrc": {...}`` -2.1.9. History service +2.1.8. History service ~~~~~~~~~~~~~~~~~~~~~~ Archives rate changes in human readable JSON format using **GIT**. @@ -241,7 +224,7 @@ Archives rate changes in human readable JSON format using **GIT**. - Config section in the CGRateS configuration file: - ``"historys": {...}`` -2.1.10. Aliases service +2.1.9. Aliases service ~~~~~~~~~~~~~~~~~~~~~~~ Generic purpose **aliasing** system. @@ -261,7 +244,7 @@ Possible applications: - Config section in the CGRateS configuration file: - ``"aliases": {...}`` -2.1.11. User service +2.1.10. User service ~~~~~~~~~~~~~~~~~~~~ Generic purpose **user** system to maintain user profiles (LDAP similarity). @@ -276,7 +259,7 @@ Generic purpose **user** system to maintain user profiles (LDAP similarity). - Config section in the CGRateS configuration file: - ``"users": {...}`` -2.1.12. PubSub service +2.1.11. PubSub service ~~~~~~~~~~~~~~~~~~~~~~ PubSub service used to expose internal events to interested external components (eg: balance ops) @@ -292,7 +275,7 @@ PubSub service used to expose internal events to interested external components - ``"pubsubs": {...}`` -2.1.13. Resource Limiter service +2.1.12. Resource Limiter service ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Resource Limiter service used to limit resources during authorization (eg: maximum calls per destination for an account) @@ -307,7 +290,7 @@ Resource Limiter service used to limit resources during authorization (eg: maxim - Config section in the CGRateS configuration file: - ``"rls": {...}`` -2.1.14. APIER RPC service +2.1.13. APIER RPC service ~~~~~~~~~~~~~~~~~~~~~~~~~ RPC service used to expose external access towards internal components. @@ -316,7 +299,7 @@ RPC service used to expose external access towards internal components. - JSON over HTTP - JSON over WebSocket -2.1.15. Cdre +2.1.14. Cdre ~~~~~~~~~~~~ Component to retrieve rated CDRs from internal CDRs database. @@ -329,7 +312,7 @@ Component to retrieve rated CDRs from internal CDRs database. - Config section in the CGRateS configuration file: - ``"cdre": {...}`` -2.1.16. Mailer +2.1.15. Mailer ~~~~~~~~~~~~~~ TBD @@ -340,7 +323,7 @@ TBD - Config section in the CGRateS configuration file: - ``"mailer": {...}`` -2.1.17. Suretax +2.1.16. Suretax ~~~~~~~~~~~~~~~ TBD @@ -446,7 +429,7 @@ Can be used to: 2.3. cgr-console ---------------- -Command line tool used to interface with the RALs (and/or Balancer) service. Able to execute **sub-commands**. +Command line tool used to interface with the RALs service. Able to execute **sub-commands**. :: diff --git a/docs/introduction.rst b/docs/introduction.rst index 46a9bf7f6..be42f969b 100644 --- a/docs/introduction.rst +++ b/docs/introduction.rst @@ -3,11 +3,11 @@ `CGRateS`_ is a *very fast* and *easily scalable* **(charging, rating, accounting, lcr, mediation, billing, authorization)** *ENGINE* targeted especially for ISPs and Telecom Operators. -It is written in `Go`_ programming language and is accessible from any programming language via JSON RPC. +It is written in `Go`_ programming language and is accessible from any programming language via JSON RPC. The code is well documented (**go doc** compliant `API docs`_) and heavily tested. (also **1300+** tests are part of the build system). -After testing various databases like `Kyoto Cabinet`_, `Apache Cassandra`_, `Redis`_ and `MongoDB`_, -the project focused on **Redis** as it delivers the best trade-off between speed, configuration and scalability. +After testing various databases like `Kyoto Cabinet`_, `Apache Cassandra`_, `Redis`_ and `MongoDB`_, +the project focused on **Redis** as it delivers the best trade-off between speed, configuration and scalability. .. important:: `MongoDB`_ **full** support is now added. @@ -26,17 +26,17 @@ To better understand the CGRateS architecture, below are some logical configurat .. note:: **RALs** - is a CGRateS component and stands for RatingAccountingLCR service. .. image:: images/Simple.png -This scenario fits most of the simple installations. The **Balancer** can be left out and the **RALs** can be queried directly. +This scenario fits most of the simple installations. .. image:: images/Normal.png -While the network grows more **RALs** can be thrown into the stack to offer more requests per seconds workload. +While the network grows more **RALs** can be thrown into the stack to offer more requests per seconds workload. This implies the usage of the **Balancer** to distribute the requests to the **RALs** running on the *different machines*. .. image:: images/Normal_ha.png -Without Balancer using HA (broadcast) .... +Without Balancer using HA (broadcast) .... .. image:: images/Complicated.png -Of course more **SessionManagers** can serve *multiple Telecom Switches* and all of them are connected to the same **Balancer**. +Of course more **SessionManagers** can serve *multiple Telecom Switches* and all of them are connected to the same **Balancer**. .. image:: images/Complicated_ha.png Without Balancer using HA (broadcast) .... @@ -51,10 +51,9 @@ Without Balancer using HA (broadcast) .... - Using most modern programming concepts like multiprocessor support, asynchronous code execution within microthreads. - Built-in data caching system per call duration. - In-Memory database with persistence over restarts. - - Use of Balancer assures High-Availability of RALs as well as increase of processing performance where that is required. - Use of Linux enterprise ready tools to assure High-Availability of the Balancer where that is required (*Supervise* for Application level availability and *LinuxHA* for Host level availability). - - High-Availability of main components is now part of CGRateS core. - + - High-Availability of main components is now part of CGRateS core. + - Modular architecture - Easy to enhance functionality by writing custom session managers or mediators. - Flexible API accessible via both **Gob** (Golang specific, increased performance) or **JSON** (platform independent, universally accessible). diff --git a/docs/overview.rst b/docs/overview.rst index 2cf54205f..9c1e0b6c2 100644 --- a/docs/overview.rst +++ b/docs/overview.rst @@ -2,33 +2,32 @@ 1. Overview =========== -Starting as a pure **billing engine**, CGRateS has evolved over the years into a reliable **real-time charging framework** able to accommodate various business cases in a *generic way*. -Meant to be pluggable into existing billing infrastructure and as non-intrusive as possible, +Starting as a pure **billing engine**, CGRateS has evolved over the years into a reliable **real-time charging framework** able to accommodate various business cases in a *generic way*. +Meant to be pluggable into existing billing infrastructure and as non-intrusive as possible, CGRateS passes the decisions about logic flow to system administrators and incorporates as less as possible business logic. Being an *"engine style"* the project focuses on providing best ratio between **functionality** ( -over 15 daemons/services implemented, -Multi-tenancy, -derived charging - eg: chaining of the business resellers, -account bundles, -LCR, -CDRStatS, -Diameter Server, -A-Number rating, +over 15 daemons/services implemented, +Multi-tenancy, +derived charging - eg: chaining of the business resellers, +account bundles, +LCR, +CDRStatS, +Diameter Server, +A-Number rating, built-in High-Availability support -agile in developing new features -) +agile in developing new features +) and **performance** ( -dedicated benchmark tool, -asynchronous request processing, -own transactional cache with majority of handled data loaded on start or reloaded during runtime, -built-in balancer -) +dedicated benchmark tool, +asynchronous request processing, +own transactional cache with majority of handled data loaded on start or reloaded during runtime, +) however not loosing focus of **quality** (over 1300 tests part of the build environment). Modular and flexible, CGRateS provides APIs over a variety of simultaneously accessible communication interfaces: - **In-process** : optimal when there is no need to split services over different processes. - - **JSON over TCP** : most preferred due to its simplicity and readability. + - **JSON over TCP** : most preferred due to its simplicity and readability. - **JSON over HTTP** : popular due to fast interoperability development. - **JSON over Websockets** : useful where 2 ways interaction over same TCP socket is required. - **GOB over TCP** : slightly faster than JSON one but only accessible for the moment out of Go (``_). @@ -46,7 +45,7 @@ CGRateS is capable of four charging modes - Session authorization via events - Charging done at the end of the session out of CDR received - Advantage: less CPU intensive due to less events processed - - Disadvantage: as balance updates happen only at the end of the session there can be costs discrepancy in case of multiple sessions out of same account + - Disadvantage: as balance updates happen only at the end of the session there can be costs discrepancy in case of multiple sessions out of same account (including going on negative balance). - \*postpaid @@ -67,16 +66,16 @@ CGRateS is capable of four charging modes - Primary component, offering the most functionality out of the subsystems. - Computes replies based on static list of "rules" defined in TariffPlan. -2.1.1. Rater +2.1.1. Rater ~~~~~~~~~~~~ - Defines the performance of the system as a whole being the "heart" component - Support for multiple TypeOfRecord (**\*voice**, **\*data**, **\*sms**, **\*generic**) - Time based calculations (activation time in the future/rate-destination timely coupled) with granular time definitions (year, month, month day, weekday, time in seconds) - Compressed destination prefixes, helping on faster destination match as well as memory consumption -- Advanced Rating capabilities: - ConnectFee (charged at beginning of the session); - RateUnit (automatic divider for the cost); - RateIncrement (increase verbosity of the charging interval); +- Advanced Rating capabilities: + ConnectFee (charged at beginning of the session); + RateUnit (automatic divider for the cost); + RateIncrement (increase verbosity of the charging interval); Grouped interval rating inside the call duration (charging each second within a session independently) - Per destination rounding: control number of decimals displayed in costs, decide rounding methods (**\*up**, **\*down**, **\*middle**) - Control of the MaxSessionCost with decision on action taken on threshold hit (**\*free**, **\*disconnect**) @@ -127,7 +126,7 @@ CGRateS is capable of four charging modes - In-memory / performance oriented - Unlimited StatQueues computing the same CDR event - Flexible queue configuration (QueueLength, TimeWindow, Metrics, CDR field filters) -- Fraud detection with automatic mitigation through action triggers +- Fraud detection with automatic mitigation through action triggers 2.4. AliaseS ------------ @@ -205,7 +204,7 @@ CGRateS is capable of four charging modes 3. CGRateS Peripherals ====================== Packaged together due to common usage - + 3.1. cgr-engine --------------- - Configured via .json files, encorporating CGRateS subsystems mentioned above @@ -241,10 +240,10 @@ Packaged together due to common usage 4.1. Fraud detection within Accounting: --------------------------------------- - Events are happening in real-time, being available during updates (eg: every n seconds of a session). -- Thresholds set by the administrator are reacting by calling a set of predefined actions **synchronously** +- Thresholds set by the administrator are reacting by calling a set of predefined actions **synchronously** (with the advantage of having account in locked state, eg. no other events are possible until decision is made) or **asynchronously** (unlocking the accounts faster) -- Two types of thresholds can be set - - **min-/max-balance** monitoring balance values +- Two types of thresholds can be set + - **min-/max-balance** monitoring balance values - **min-/max-usage** counters (eg: amount of minutes to specific destination). - Middle session control (sessions can be disconnected as fraud is detected diff --git a/engine/responder.go b/engine/responder.go index 6eeb12262..42210bd42 100644 --- a/engine/responder.go +++ b/engine/responder.go @@ -19,14 +19,11 @@ package engine import ( "errors" - "fmt" - "net/rpc" "reflect" "runtime" "strings" "time" - "github.com/cgrates/cgrates/balancer2go" "github.com/cgrates/cgrates/cache" "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/guardian" @@ -48,7 +45,6 @@ type AttrGetLcr struct { } type Responder struct { - Bal *balancer2go.Balancer ExitChan chan bool Stats rpcclient.RpcClientConnection Timeout time.Duration @@ -94,19 +90,14 @@ func (rs *Responder) GetCost(arg *CallDescriptor, reply *CallCost) (err error) { }, arg, utils.EXTRA_FIELDS); err != nil && err != utils.ErrNotFound { return err } - if rs.Bal != nil { - r, e := rs.getCallCost(arg, "Responder.GetCost") - *reply, err = *r, e - } else { - r, e := guardian.Guardian.Guard(func() (interface{}, error) { - return arg.GetCost() - }, 0, arg.GetAccountKey()) - if r != nil { - *reply = *r.(*CallCost) - } - if e != nil { - return e - } + r, e := guardian.Guardian.Guard(func() (interface{}, error) { + return arg.GetCost() + }, 0, arg.GetAccountKey()) + if r != nil { + *reply = *r.(*CallCost) + } + if e != nil { + return e } return } @@ -132,17 +123,11 @@ func (rs *Responder) Debit(arg *CallDescriptor, reply *CallCost) (err error) { }, arg, utils.EXTRA_FIELDS); err != nil && err != utils.ErrNotFound { return err } - - if rs.Bal != nil { - r, e := rs.getCallCost(arg, "Responder.Debit") - *reply, err = *r, e - } else { - r, e := arg.Debit() - if e != nil { - return e - } else if r != nil { - *reply = *r - } + r, e := arg.Debit() + if e != nil { + return e + } else if r != nil { + *reply = *r } return } @@ -175,20 +160,14 @@ func (rs *Responder) MaxDebit(arg *CallDescriptor, reply *CallCost) (err error) }, arg, utils.EXTRA_FIELDS); err != nil && err != utils.ErrNotFound { return err } - - if rs.Bal != nil { - r, e := rs.getCallCost(arg, "Responder.MaxDebit") - *reply, err = *r, e - } else { - r, e := arg.MaxDebit() - if e != nil { - rs.getCache().Cache(cacheKey, &cache.CacheItem{ - Err: e, - }) - return e - } else if r != nil { - *reply = *r - } + r, e := arg.MaxDebit() + if e != nil { + rs.getCache().Cache(cacheKey, &cache.CacheItem{ + Err: e, + }) + return e + } else if r != nil { + *reply = *r } rs.getCache().Cache(cacheKey, &cache.CacheItem{ Value: reply, @@ -228,12 +207,7 @@ func (rs *Responder) RefundIncrements(arg *CallDescriptor, reply *float64) (err }) return err } - - if rs.Bal != nil { - *reply, err = rs.callMethod(arg, "Responder.RefundIncrements") - } else { - err = arg.RefundIncrements() - } + err = arg.RefundIncrements() rs.getCache().Cache(cacheKey, &cache.CacheItem{ Value: reply, Err: err, @@ -272,12 +246,7 @@ func (rs *Responder) RefundRounding(arg *CallDescriptor, reply *float64) (err er }) return err } - - if rs.Bal != nil { - *reply, err = rs.callMethod(arg, "Responder.RefundRounding") - } else { - err = arg.RefundRounding() - } + err = arg.RefundRounding() rs.getCache().Cache(cacheKey, &cache.CacheItem{ Value: reply, Err: err, @@ -306,21 +275,13 @@ func (rs *Responder) GetMaxSessionTime(arg *CallDescriptor, reply *float64) (err }, arg, utils.EXTRA_FIELDS); err != nil && err != utils.ErrNotFound { return err } - - if rs.Bal != nil { - *reply, err = rs.callMethod(arg, "Responder.GetMaxSessionTime") - } else { - r, e := arg.GetMaxSessionDuration() - *reply, err = float64(r), e - } + r, e := arg.GetMaxSessionDuration() + *reply, err = float64(r), e return } // Returns MaxSessionTime for an event received in SessionManager, considering DerivedCharging for it func (rs *Responder) GetDerivedMaxSessionTime(ev *CDR, reply *float64) error { - if rs.Bal != nil { - return errors.New("unsupported method on the balancer") - } cacheKey := utils.GET_DERIV_MAX_SESS_TIME + ev.CGRID + ev.RunID if item, err := rs.getCache().Get(cacheKey); err == nil && item != nil { if item.Value != nil { @@ -426,9 +387,6 @@ func (rs *Responder) GetDerivedMaxSessionTime(ev *CDR, reply *float64) error { // Used by SM to get all the prepaid CallDescriptors attached to a session func (rs *Responder) GetSessionRuns(ev *CDR, sRuns *[]*SessionRun) error { - if rs.Bal != nil { - return errors.New("Unsupported method on the balancer") - } cacheKey := utils.GET_SESS_RUNS_CACHE_PREFIX + ev.CGRID if item, err := rs.getCache().Get(cacheKey); err == nil && item != nil { if item.Value != nil { @@ -518,9 +476,6 @@ func (rs *Responder) GetSessionRuns(ev *CDR, sRuns *[]*SessionRun) error { } func (rs *Responder) GetDerivedChargers(attrs *utils.AttrDerivedChargers, dcs *utils.DerivedChargers) error { - if rs.Bal != nil { - return errors.New("BALANCER_UNSUPPORTED_METHOD") - } if dcsH, err := HandleGetDerivedChargers(dataStorage, attrs); err != nil { return err } else if dcsH != nil { @@ -584,9 +539,6 @@ func (rs *Responder) Status(arg string, reply *map[string]interface{}) (err erro runtime.ReadMemStats(memstats) response := make(map[string]interface{}) response[utils.InstanceID] = config.CgrConfig().InstanceID - if rs.Bal != nil { - response["Raters"] = rs.Bal.GetClientAddresses() - } response["MemoryUsage"] = utils.SizeFmt(float64(memstats.HeapAlloc), "") response[utils.ActiveGoroutines] = runtime.NumGoroutine() response["Footprint"] = utils.SizeFmt(float64(memstats.Sys), "") @@ -595,9 +547,6 @@ func (rs *Responder) Status(arg string, reply *map[string]interface{}) (err erro } func (rs *Responder) Shutdown(arg string, reply *string) (err error) { - if rs.Bal != nil { - rs.Bal.Shutdown("Responder.Shutdown") - } dataStorage.Close() cdrStorage.Close() defer func() { rs.ExitChan <- true }() @@ -605,83 +554,6 @@ func (rs *Responder) Shutdown(arg string, reply *string) (err error) { return } -/* -The function that gets the information from the raters using balancer. -*/ -func (rs *Responder) getCallCost(key *CallDescriptor, method string) (reply *CallCost, err error) { - err = errors.New("") //not nil value - for err != nil { - client := rs.Bal.Balance() - if client == nil { - utils.Logger.Info(" Waiting for raters to register...") - time.Sleep(1 * time.Second) // wait one second and retry - } else { - _, err = guardian.Guardian.Guard(func() (interface{}, error) { - err = client.Call(method, *key, reply) - return reply, err - }, 0, key.GetAccountKey()) - if err != nil { - utils.Logger.Err(fmt.Sprintf(" Got en error from rater: %v", err)) - } - } - } - return -} - -/* -The function that gets the information from the raters using balancer. -*/ -func (rs *Responder) callMethod(key *CallDescriptor, method string) (reply float64, err error) { - err = errors.New("") //not nil value - for err != nil { - client := rs.Bal.Balance() - if client == nil { - utils.Logger.Info("Waiting for raters to register...") - time.Sleep(1 * time.Second) // wait one second and retry - } else { - _, err = guardian.Guardian.Guard(func() (interface{}, error) { - err = client.Call(method, *key, &reply) - return reply, err - }, 0, key.GetAccountKey()) - if err != nil { - utils.Logger.Info(fmt.Sprintf("Got en error from rater: %v", err)) - } - } - } - return -} - -/* -RPC method that receives a rater address, connects to it and ads the pair to the rater list for balancing -*/ -func (rs *Responder) RegisterRater(clientAddress string, replay *int) error { - utils.Logger.Info(fmt.Sprintf("Started rater %v registration...", clientAddress)) - time.Sleep(2 * time.Second) // wait a second for Rater to start serving - client, err := rpc.Dial("tcp", clientAddress) - if err != nil { - utils.Logger.Err("Could not connect to client!") - return err - } - rs.Bal.AddClient(clientAddress, client) - utils.Logger.Info(fmt.Sprintf("Rater %v registered succesfully.", clientAddress)) - return nil -} - -/* -RPC method that recives a rater addres gets the connections and closes it and removes the pair from rater list. -*/ -func (rs *Responder) UnRegisterRater(clientAddress string, replay *int) error { - client, ok := rs.Bal.GetClient(clientAddress) - if ok { - client.Close() - rs.Bal.RemoveClient(clientAddress) - utils.Logger.Info(fmt.Sprintf("Rater %v unregistered succesfully.", clientAddress)) - } else { - utils.Logger.Info(fmt.Sprintf("Server %v was not on my watch!", clientAddress)) - } - return nil -} - func (rs *Responder) GetTimeout(i int, d *time.Duration) error { *d = rs.Timeout return nil