diff --git a/analyzers/codec.go b/analyzers/codec.go index d0c3d1cff..0428095a7 100644 --- a/analyzers/codec.go +++ b/analyzers/codec.go @@ -24,7 +24,7 @@ import ( "time" ) -func (aS *AnalyzerService) NewServerCodec(sc rpc.ServerCodec, enc, from, to string) rpc.ServerCodec { +func NewServerCodec(sc rpc.ServerCodec, aS *AnalyzerService, enc, from, to string) rpc.ServerCodec { return &AnalyzerServerCodec{ sc: sc, reqs: make(map[uint64]*rpcAPI), diff --git a/analyzers/codec_test.go b/analyzers/codec_test.go index 772eda32f..ad2e075b3 100644 --- a/analyzers/codec_test.go +++ b/analyzers/codec_test.go @@ -65,7 +65,7 @@ func TestNewServerCodec(t *testing.T) { t.Fatal(err) } - codec := anz.NewServerCodec(new(mockServerCodec), utils.MetaJSON, "127.0.0.1:5565", "127.0.0.1:2012") + codec := NewServerCodec(new(mockServerCodec), anz, utils.MetaJSON, "127.0.0.1:5565", "127.0.0.1:2012") r := new(rpc.Request) expR := &rpc.Request{ Seq: 0, diff --git a/apier/v1/concreqs_it_test.go b/apier/v1/concreqs_it_test.go index 9f124dc37..4cae6eb78 100644 --- a/apier/v1/concreqs_it_test.go +++ b/apier/v1/concreqs_it_test.go @@ -40,57 +40,57 @@ import ( ) var ( - concReqsCfgPath string - concReqsCfg *config.CGRConfig - concReqsRPC *rpc.Client - concReqsBiRPC *rpc2.Client - concReqsConfigDIR string //run tests for specific configuration + capsCfgPath string + capsCfg *config.CGRConfig + capsRPC *rpc.Client + capsBiRPC *rpc2.Client + capsConfigDIR string //run tests for specific configuration - sTestsConcReqs = []func(t *testing.T){ - testConcReqsInitCfg, - testConcReqsStartEngine, - testConcReqsRPCConn, - testConcReqsBusyAPIs, - testConcReqsQueueAPIs, - testConcReqsOnHTTPBusy, - testConcReqsOnHTTPQueue, - testConcReqsOnBiJSONBusy, - testConcReqsOnBiJSONQueue, - testConcReqsKillEngine, + sTestsCaps = []func(t *testing.T){ + testCapsInitCfg, + testCapsStartEngine, + testCapsRPCConn, + testCapsBusyAPIs, + testCapsQueueAPIs, + testCapsOnHTTPBusy, + testCapsOnHTTPQueue, + testCapsOnBiJSONBusy, + testCapsOnBiJSONQueue, + testCapsKillEngine, } // used by benchmarks - concReqsOnce sync.Once - concReqLastCfgDir string + capsOnce sync.Once + capsLastCfgDir string ) //Test start here -func TestConcReqsBusyJSON(t *testing.T) { - concReqsConfigDIR = "conc_reqs_busy" - for _, stest := range sTestsConcReqs { - t.Run(concReqsConfigDIR, stest) +func TestCapsBusyJSON(t *testing.T) { + capsConfigDIR = "conc_reqs_busy" + for _, stest := range sTestsCaps { + t.Run(capsConfigDIR, stest) } } -func TestConcReqsQueueJSON(t *testing.T) { - concReqsConfigDIR = "conc_reqs_queue" - for _, stest := range sTestsConcReqs { - t.Run(concReqsConfigDIR, stest) +func TestCapsQueueJSON(t *testing.T) { + capsConfigDIR = "conc_reqs_queue" + for _, stest := range sTestsCaps { + t.Run(capsConfigDIR, stest) } } -func testConcReqsInitCfg(t *testing.T) { +func testCapsInitCfg(t *testing.T) { var err error - concReqsCfgPath = path.Join(*dataDir, "conf", "samples", concReqsConfigDIR) - concReqsCfg, err = config.NewCGRConfigFromPath(concReqsCfgPath) + capsCfgPath = path.Join(*dataDir, "conf", "samples", capsConfigDIR) + capsCfg, err = config.NewCGRConfigFromPath(capsCfgPath) if err != nil { t.Error(err) } } // Start CGR Engine -func testConcReqsStartEngine(t *testing.T) { - if _, err := engine.StopStartEngine(concReqsCfgPath, *waitRater); err != nil { +func testCapsStartEngine(t *testing.T) { + if _, err := engine.StopStartEngine(capsCfgPath, *waitRater); err != nil { t.Fatal(err) } } @@ -102,20 +102,20 @@ func handlePing(clnt *rpc2.Client, arg *utils.DurationArgs, reply *string) error } // Connect rpc client to rater -func testConcReqsRPCConn(t *testing.T) { +func testCapsRPCConn(t *testing.T) { var err error - concReqsRPC, err = newRPCClient(concReqsCfg.ListenCfg()) // We connect over JSON so we can also troubleshoot if needed + capsRPC, err = newRPCClient(capsCfg.ListenCfg()) // We connect over JSON so we can also troubleshoot if needed if err != nil { t.Fatal(err) } - if concReqsBiRPC, err = utils.NewBiJSONrpcClient(concReqsCfg.SessionSCfg().ListenBijson, + if capsBiRPC, err = utils.NewBiJSONrpcClient(capsCfg.SessionSCfg().ListenBijson, nil); err != nil { t.Fatal(err) } } -func testConcReqsBusyAPIs(t *testing.T) { - if concReqsConfigDIR != "conc_reqs_busy" { +func testCapsBusyAPIs(t *testing.T) { + if capsConfigDIR != "conc_reqs_busy" { t.SkipNow() } var failedAPIs int @@ -125,7 +125,7 @@ func testConcReqsBusyAPIs(t *testing.T) { wg.Add(1) go func() { var resp string - if err := concReqsRPC.Call(utils.CoreSv1Sleep, + if err := capsRPC.Call(utils.CoreSv1Sleep, &utils.DurationArgs{Duration: 10 * time.Millisecond}, &resp); err != nil { lock.Lock() @@ -143,8 +143,8 @@ func testConcReqsBusyAPIs(t *testing.T) { } } -func testConcReqsQueueAPIs(t *testing.T) { - if concReqsConfigDIR != "conc_reqs_queue" { +func testCapsQueueAPIs(t *testing.T) { + if capsConfigDIR != "conc_reqs_queue" { t.SkipNow() } wg := new(sync.WaitGroup) @@ -152,7 +152,7 @@ func testConcReqsQueueAPIs(t *testing.T) { wg.Add(1) go func() { var resp string - if err := concReqsRPC.Call(utils.CoreSv1Sleep, + if err := capsRPC.Call(utils.CoreSv1Sleep, &utils.DurationArgs{Duration: 10 * time.Millisecond}, &resp); err != nil { wg.Done() @@ -165,8 +165,8 @@ func testConcReqsQueueAPIs(t *testing.T) { wg.Wait() } -func testConcReqsOnHTTPBusy(t *testing.T) { - if concReqsConfigDIR != "conc_reqs_busy" { +func testCapsOnHTTPBusy(t *testing.T) { + if capsConfigDIR != "conc_reqs_busy" { t.SkipNow() } var fldAPIs int64 @@ -203,8 +203,8 @@ func testConcReqsOnHTTPBusy(t *testing.T) { } } -func testConcReqsOnHTTPQueue(t *testing.T) { - if concReqsConfigDIR != "conc_reqs_queue" { +func testCapsOnHTTPQueue(t *testing.T) { + if capsConfigDIR != "conc_reqs_queue" { t.SkipNow() } wg := new(sync.WaitGroup) @@ -224,8 +224,8 @@ func testConcReqsOnHTTPQueue(t *testing.T) { wg.Wait() } -func testConcReqsOnBiJSONBusy(t *testing.T) { - if concReqsConfigDIR != "conc_reqs_busy" { +func testCapsOnBiJSONBusy(t *testing.T) { + if capsConfigDIR != "conc_reqs_busy" { t.SkipNow() } var failedAPIs int @@ -235,7 +235,7 @@ func testConcReqsOnBiJSONBusy(t *testing.T) { wg.Add(1) go func() { var resp string - if err := concReqsBiRPC.Call(utils.SessionSv1Sleep, + if err := capsBiRPC.Call(utils.SessionSv1Sleep, &utils.DurationArgs{Duration: 10 * time.Millisecond}, &resp); err != nil { lock.Lock() @@ -253,8 +253,8 @@ func testConcReqsOnBiJSONBusy(t *testing.T) { } } -func testConcReqsOnBiJSONQueue(t *testing.T) { - if concReqsConfigDIR != "conc_reqs_queue" { +func testCapsOnBiJSONQueue(t *testing.T) { + if capsConfigDIR != "conc_reqs_queue" { t.SkipNow() } wg := new(sync.WaitGroup) @@ -262,7 +262,7 @@ func testConcReqsOnBiJSONQueue(t *testing.T) { wg.Add(1) go func() { var resp string - if err := concReqsBiRPC.Call(utils.SessionSv1Sleep, + if err := capsBiRPC.Call(utils.SessionSv1Sleep, &utils.DurationArgs{Duration: 10 * time.Millisecond}, &resp); err != nil { wg.Done() @@ -275,7 +275,7 @@ func testConcReqsOnBiJSONQueue(t *testing.T) { wg.Wait() } -func testConcReqsKillEngine(t *testing.T) { +func testCapsKillEngine(t *testing.T) { time.Sleep(100 * time.Millisecond) if err := engine.KillEngine(100); err != nil { t.Error(err) @@ -285,20 +285,20 @@ func testConcReqsKillEngine(t *testing.T) { func benchmarkInit(b *testing.B, cfgDir string) { b.StopTimer() // restart cgrates only if needed - if cfgDir != concReqLastCfgDir { - concReqsOnce = sync.Once{} + if cfgDir != capsLastCfgDir { + capsOnce = sync.Once{} } - concReqsOnce.Do(func() { - concReqLastCfgDir = cfgDir + capsOnce.Do(func() { + capsLastCfgDir = cfgDir var err error - concReqsCfgPath = path.Join(*dataDir, "conf", "samples", cfgDir) - if concReqsCfg, err = config.NewCGRConfigFromPath(concReqsCfgPath); err != nil { + capsCfgPath = path.Join(*dataDir, "conf", "samples", cfgDir) + if capsCfg, err = config.NewCGRConfigFromPath(capsCfgPath); err != nil { b.Fatal(err) } - if _, err := engine.StopStartEngine(concReqsCfgPath, *waitRater); err != nil { + if _, err := engine.StopStartEngine(capsCfgPath, *waitRater); err != nil { b.Fatal(err) } - if concReqsRPC, err = newRPCClient(concReqsCfg.ListenCfg()); err != nil { + if capsRPC, err = newRPCClient(capsCfg.ListenCfg()); err != nil { b.Fatal(err) } // b.Logf("Preparation done for %s", cfgDir) @@ -309,18 +309,18 @@ func benchmarkInit(b *testing.B, cfgDir string) { func benchmarkCall(b *testing.B) { var rply map[string]interface{} for i := 0; i < b.N; i++ { - if err := concReqsRPC.Call(utils.CoreSv1Status, &utils.TenantWithOpts{}, &rply); err != nil { + if err := capsRPC.Call(utils.CoreSv1Status, &utils.TenantWithOpts{}, &rply); err != nil { b.Error(err) } } } -func BenchmarkConcReqWithLimit(b *testing.B) { +func BenchmarkcapsWithLimit(b *testing.B) { benchmarkInit(b, "conc_reqs_queue_bench") benchmarkCall(b) } -func BenchmarkConcReqWithoutLimit(b *testing.B) { +func BenchmarkcapsWithoutLimit(b *testing.B) { benchmarkInit(b, "tutmysql") benchmarkCall(b) } diff --git a/apier/v1/core.go b/apier/v1/core.go index 06419416e..53b2f2392 100644 --- a/apier/v1/core.go +++ b/apier/v1/core.go @@ -21,17 +21,17 @@ package v1 import ( "time" - "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/utils" ) -func NewCoreSv1(cS *engine.CoreService) *CoreSv1 { +func NewCoreSv1(cS *cores.CoreService) *CoreSv1 { return &CoreSv1{cS: cS} } // CoreSv1 exports RPC from RLs type CoreSv1 struct { - cS *engine.CoreService + cS *cores.CoreService } // Call implements rpcclient.ClientConnector interface for internal RPC diff --git a/apier/v1/precache_it_test.go b/apier/v1/precache_it_test.go index 9c3fb741e..323240179 100644 --- a/apier/v1/precache_it_test.go +++ b/apier/v1/precache_it_test.go @@ -229,6 +229,7 @@ func testPrecacheGetCacheStatsAfterRestart(t *testing.T) { Items: 1, }, utils.CacheSTIR: {}, + utils.CacheCapsEvents: {}, utils.CacheEventCharges: {}, utils.CacheRouteFilterIndexes: { Items: 6, diff --git a/apier/v1/sessions.go b/apier/v1/sessions.go index 57762b947..7fbcd59e3 100644 --- a/apier/v1/sessions.go +++ b/apier/v1/sessions.go @@ -19,22 +19,23 @@ along with this program. If not, see package v1 import ( + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/dispatchers" "github.com/cgrates/cgrates/sessions" "github.com/cgrates/cgrates/utils" ) -func NewSessionSv1(sS *sessions.SessionS, concReqs *utils.ConcReqs) *SessionSv1 { +func NewSessionSv1(sS *sessions.SessionS, caps *cores.Caps) *SessionSv1 { return &SessionSv1{ - sS: sS, - concReqs: concReqs, + sS: sS, + caps: caps, } } // SessionSv1 exports RPC from SessionSv1 type SessionSv1 struct { - sS *sessions.SessionS - concReqs *utils.ConcReqs + sS *sessions.SessionS + caps *cores.Caps } func (ssv1 *SessionSv1) AuthorizeEvent(args *sessions.V1AuthorizeArgs, diff --git a/apier/v1/sessionsbirpc.go b/apier/v1/sessionsbirpc.go index c6a5bdd76..6e4d9b69b 100644 --- a/apier/v1/sessionsbirpc.go +++ b/apier/v1/sessionsbirpc.go @@ -67,242 +67,242 @@ func (ssv1 *SessionSv1) Handlers() map[string]interface{} { func (ssv1 *SessionSv1) BiRPCv1AuthorizeEvent(clnt *rpc2.Client, args *sessions.V1AuthorizeArgs, rply *sessions.V1AuthorizeReply) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1AuthorizeEvent(clnt, args, rply) } func (ssv1 *SessionSv1) BiRPCv1AuthorizeEventWithDigest(clnt *rpc2.Client, args *sessions.V1AuthorizeArgs, rply *sessions.V1AuthorizeReplyWithDigest) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1AuthorizeEventWithDigest(clnt, args, rply) } func (ssv1 *SessionSv1) BiRPCv1InitiateSession(clnt *rpc2.Client, args *sessions.V1InitSessionArgs, rply *sessions.V1InitSessionReply) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1InitiateSession(clnt, args, rply) } func (ssv1 *SessionSv1) BiRPCv1InitiateSessionWithDigest(clnt *rpc2.Client, args *sessions.V1InitSessionArgs, rply *sessions.V1InitReplyWithDigest) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1InitiateSessionWithDigest(clnt, args, rply) } func (ssv1 *SessionSv1) BiRPCv1UpdateSession(clnt *rpc2.Client, args *sessions.V1UpdateSessionArgs, rply *sessions.V1UpdateSessionReply) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1UpdateSession(clnt, args, rply) } func (ssv1 *SessionSv1) BiRPCv1SyncSessions(clnt *rpc2.Client, args *utils.TenantWithOpts, rply *string) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1SyncSessions(clnt, &utils.TenantWithOpts{}, rply) } func (ssv1 *SessionSv1) BiRPCv1TerminateSession(clnt *rpc2.Client, args *sessions.V1TerminateSessionArgs, rply *string) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1TerminateSession(clnt, args, rply) } func (ssv1 *SessionSv1) BiRPCv1ProcessCDR(clnt *rpc2.Client, cgrEv *utils.CGREventWithOpts, rply *string) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1ProcessCDR(clnt, cgrEv, rply) } func (ssv1 *SessionSv1) BiRPCv1ProcessMessage(clnt *rpc2.Client, args *sessions.V1ProcessMessageArgs, rply *sessions.V1ProcessMessageReply) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1ProcessMessage(clnt, args, rply) } func (ssv1 *SessionSv1) BiRPCv1ProcessEvent(clnt *rpc2.Client, args *sessions.V1ProcessEventArgs, rply *sessions.V1ProcessEventReply) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1ProcessEvent(clnt, args, rply) } func (ssv1 *SessionSv1) BiRPCv1GetCost(clnt *rpc2.Client, args *sessions.V1ProcessEventArgs, rply *sessions.V1GetCostReply) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1GetCost(clnt, args, rply) } func (ssv1 *SessionSv1) BiRPCv1GetActiveSessions(clnt *rpc2.Client, args *utils.SessionFilter, rply *[]*sessions.ExternalSession) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1GetActiveSessions(clnt, args, rply) } func (ssv1 *SessionSv1) BiRPCv1GetActiveSessionsCount(clnt *rpc2.Client, args *utils.SessionFilter, rply *int) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1GetActiveSessionsCount(clnt, args, rply) } func (ssv1 *SessionSv1) BiRPCv1GetPassiveSessions(clnt *rpc2.Client, args *utils.SessionFilter, rply *[]*sessions.ExternalSession) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1GetPassiveSessions(clnt, args, rply) } func (ssv1 *SessionSv1) BiRPCv1GetPassiveSessionsCount(clnt *rpc2.Client, args *utils.SessionFilter, rply *int) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1GetPassiveSessionsCount(clnt, args, rply) } func (ssv1 *SessionSv1) BiRPCv1ForceDisconnect(clnt *rpc2.Client, args *utils.SessionFilter, rply *string) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1ForceDisconnect(clnt, args, rply) } func (ssv1 *SessionSv1) BiRPCv1RegisterInternalBiJSONConn(clnt *rpc2.Client, args string, rply *string) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1RegisterInternalBiJSONConn(clnt, args, rply) } func (ssv1 *SessionSv1) BiRPCPing(clnt *rpc2.Client, ign *utils.CGREventWithOpts, reply *string) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.Ping(ign, reply) } func (ssv1 *SessionSv1) BiRPCv1ReplicateSessions(clnt *rpc2.Client, args sessions.ArgsReplicateSessions, reply *string) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.BiRPCv1ReplicateSessions(clnt, args, reply) } func (ssv1 *SessionSv1) BiRPCv1SetPassiveSession(clnt *rpc2.Client, args *sessions.Session, reply *string) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1SetPassiveSession(clnt, args, reply) } func (ssv1 *SessionSv1) BiRPCv1ActivateSessions(clnt *rpc2.Client, args *utils.SessionIDsWithArgsDispatcher, reply *string) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1ActivateSessions(clnt, args, reply) } func (ssv1 *SessionSv1) BiRPCv1DeactivateSessions(clnt *rpc2.Client, args *utils.SessionIDsWithArgsDispatcher, reply *string) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1DeactivateSessions(clnt, args, reply) } @@ -310,11 +310,11 @@ func (ssv1 *SessionSv1) BiRPCv1DeactivateSessions(clnt *rpc2.Client, // BiRPCV1ReAuthorize sends the RAR for filterd sessions func (ssv1 *SessionSv1) BiRPCV1ReAuthorize(clnt *rpc2.Client, args *utils.SessionFilter, reply *string) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1ReAuthorize(clnt, args, reply) } @@ -322,11 +322,11 @@ func (ssv1 *SessionSv1) BiRPCV1ReAuthorize(clnt *rpc2.Client, // BiRPCV1DisconnectPeer sends the DPR for the OriginHost and OriginRealm func (ssv1 *SessionSv1) BiRPCV1DisconnectPeer(clnt *rpc2.Client, args *utils.DPRArgs, reply *string) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1DisconnectPeer(clnt, args, reply) } @@ -334,11 +334,11 @@ func (ssv1 *SessionSv1) BiRPCV1DisconnectPeer(clnt *rpc2.Client, // BiRPCV1STIRAuthenticate checks the identity using STIR/SHAKEN func (ssv1 *SessionSv1) BiRPCV1STIRAuthenticate(clnt *rpc2.Client, args *sessions.V1STIRAuthenticateArgs, reply *string) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1STIRAuthenticate(clnt, args, reply) } @@ -346,22 +346,22 @@ func (ssv1 *SessionSv1) BiRPCV1STIRAuthenticate(clnt *rpc2.Client, // BiRPCV1STIRIdentity creates the identity for STIR/SHAKEN func (ssv1 *SessionSv1) BiRPCV1STIRIdentity(clnt *rpc2.Client, args *sessions.V1STIRIdentityArgs, reply *string) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } return ssv1.sS.BiRPCv1STIRIdentity(nil, args, reply) } func (ssv1 *SessionSv1) BiRPCV1Sleep(clnt *rpc2.Client, arg *utils.DurationArgs, reply *string) (err error) { - if ssv1.concReqs.IsLimited() { - if err = ssv1.concReqs.Allocate(); err != nil { + if ssv1.caps.IsLimited() { + if err = ssv1.caps.Allocate(); err != nil { return } - defer ssv1.concReqs.Deallocate() + defer ssv1.caps.Deallocate() } time.Sleep(arg.Duration) *reply = utils.OK diff --git a/apier/v1/smg.go b/apier/v1/smg.go index 48be647c8..27d834d68 100644 --- a/apier/v1/smg.go +++ b/apier/v1/smg.go @@ -19,22 +19,22 @@ along with this program. If not, see package v1 import ( + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/sessions" - "github.com/cgrates/cgrates/utils" ) -func NewSMGenericV1(sS *sessions.SessionS, concReqs *utils.ConcReqs) *SMGenericV1 { +func NewSMGenericV1(sS *sessions.SessionS, caps *cores.Caps) *SMGenericV1 { return &SMGenericV1{ - Ss: sS, - concReqs: concReqs, + Ss: sS, + caps: caps, } } // Exports RPC from SMGeneric // DEPRECATED, use SessionSv1 instead type SMGenericV1 struct { - Ss *sessions.SessionS - concReqs *utils.ConcReqs + Ss *sessions.SessionS + caps *cores.Caps } // Returns MaxUsage (for calls in seconds), -1 for no limit diff --git a/apier/v1/smgbirpc.go b/apier/v1/smgbirpc.go index 8ca2de52d..afec23c49 100644 --- a/apier/v1/smgbirpc.go +++ b/apier/v1/smgbirpc.go @@ -36,11 +36,11 @@ func (smgv1 *SMGenericV1) Handlers() map[string]interface{} { /// Returns MaxUsage (for calls in seconds), -1 for no limit func (smgv1 *SMGenericV1) BiRPCV1GetMaxUsage(clnt *rpc2.Client, ev map[string]interface{}, maxUsage *float64) (err error) { - if smgv1.concReqs.IsLimited() { - if err = smgv1.concReqs.Allocate(); err != nil { + if smgv1.caps.IsLimited() { + if err = smgv1.caps.Allocate(); err != nil { return } - defer smgv1.concReqs.Deallocate() + defer smgv1.caps.Deallocate() } return smgv1.Ss.BiRPCV1GetMaxUsage(clnt, ev, maxUsage) } @@ -48,11 +48,11 @@ func (smgv1 *SMGenericV1) BiRPCV1GetMaxUsage(clnt *rpc2.Client, // Called on session start, returns the maximum number of seconds the session can last func (smgv1 *SMGenericV1) BiRPCV1InitiateSession(clnt *rpc2.Client, ev map[string]interface{}, maxUsage *float64) (err error) { - if smgv1.concReqs.IsLimited() { - if err = smgv1.concReqs.Allocate(); err != nil { + if smgv1.caps.IsLimited() { + if err = smgv1.caps.Allocate(); err != nil { return } - defer smgv1.concReqs.Deallocate() + defer smgv1.caps.Deallocate() } return smgv1.Ss.BiRPCV1InitiateSession(clnt, ev, maxUsage) } @@ -60,11 +60,11 @@ func (smgv1 *SMGenericV1) BiRPCV1InitiateSession(clnt *rpc2.Client, // Interim updates, returns remaining duration from the rater func (smgv1 *SMGenericV1) BiRPCV1UpdateSession(clnt *rpc2.Client, ev map[string]interface{}, maxUsage *float64) (err error) { - if smgv1.concReqs.IsLimited() { - if err = smgv1.concReqs.Allocate(); err != nil { + if smgv1.caps.IsLimited() { + if err = smgv1.caps.Allocate(); err != nil { return } - defer smgv1.concReqs.Deallocate() + defer smgv1.caps.Deallocate() } return smgv1.Ss.BiRPCV1UpdateSession(clnt, ev, maxUsage) } @@ -72,11 +72,11 @@ func (smgv1 *SMGenericV1) BiRPCV1UpdateSession(clnt *rpc2.Client, // Called on session end, should stop debit loop func (smgv1 *SMGenericV1) BiRPCV1TerminateSession(clnt *rpc2.Client, ev map[string]interface{}, reply *string) (err error) { - if smgv1.concReqs.IsLimited() { - if err = smgv1.concReqs.Allocate(); err != nil { + if smgv1.caps.IsLimited() { + if err = smgv1.caps.Allocate(); err != nil { return } - defer smgv1.concReqs.Deallocate() + defer smgv1.caps.Deallocate() } return smgv1.Ss.BiRPCV1TerminateSession(clnt, ev, reply) } @@ -84,11 +84,11 @@ func (smgv1 *SMGenericV1) BiRPCV1TerminateSession(clnt *rpc2.Client, // Called on session end, should send the CDR to CDRS func (smgv1 *SMGenericV1) BiRPCV1ProcessCDR(clnt *rpc2.Client, ev map[string]interface{}, reply *string) (err error) { - if smgv1.concReqs.IsLimited() { - if err = smgv1.concReqs.Allocate(); err != nil { + if smgv1.caps.IsLimited() { + if err = smgv1.caps.Allocate(); err != nil { return } - defer smgv1.concReqs.Deallocate() + defer smgv1.caps.Deallocate() } return smgv1.Ss.BiRPCV1ProcessCDR(clnt, ev, reply) } diff --git a/cmd/cgr-engine/cgr-engine.go b/cmd/cgr-engine/cgr-engine.go index b4e7206a9..88413e46a 100644 --- a/cmd/cgr-engine/cgr-engine.go +++ b/cmd/cgr-engine/cgr-engine.go @@ -32,6 +32,7 @@ import ( "syscall" "time" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/dispatcherh" "github.com/cgrates/cgrates/loaders" @@ -74,7 +75,7 @@ func startFilterService(filterSChan chan *engine.FilterS, cacheS *engine.CacheS, // initCacheS inits the CacheS and starts precaching as well as populating internal channel for RPC conns func initCacheS(internalCacheSChan chan rpcclient.ClientConnector, - server *utils.Server, dm *engine.DataManager, exitChan chan bool, + server *cores.Server, dm *engine.DataManager, exitChan chan bool, anz *services.AnalyzerService) (chS *engine.CacheS) { chS = engine.NewCacheS(cfg, dm) go func() { @@ -96,7 +97,7 @@ func initCacheS(internalCacheSChan chan rpcclient.ClientConnector, return } -func initGuardianSv1(internalGuardianSChan chan rpcclient.ClientConnector, server *utils.Server, +func initGuardianSv1(internalGuardianSChan chan rpcclient.ClientConnector, server *cores.Server, anz *services.AnalyzerService) { grdSv1 := v1.NewGuardianSv1() if !cfg.DispatcherSCfg().Enabled { @@ -109,9 +110,9 @@ func initGuardianSv1(internalGuardianSChan chan rpcclient.ClientConnector, serve internalGuardianSChan <- rpc } -func initCoreSv1(internalCoreSv1Chan chan rpcclient.ClientConnector, server *utils.Server, - anz *services.AnalyzerService) { - cSv1 := v1.NewCoreSv1(engine.NewCoreService()) +func initCoreSv1(internalCoreSv1Chan chan rpcclient.ClientConnector, server *cores.Server, + anz *services.AnalyzerService, cfg *config.CGRConfig, caps *cores.Caps, exitChan chan bool) { + cSv1 := v1.NewCoreSv1(cores.NewCoreService(cfg, caps, exitChan)) if !cfg.DispatcherSCfg().Enabled { server.RpcRegister(cSv1) } @@ -123,7 +124,7 @@ func initCoreSv1(internalCoreSv1Chan chan rpcclient.ClientConnector, server *uti } func initServiceManagerV1(internalServiceManagerChan chan rpcclient.ClientConnector, - srvMngr *servmanager.ServiceManager, server *utils.Server, + srvMngr *servmanager.ServiceManager, server *cores.Server, anz *services.AnalyzerService) { if !cfg.DispatcherSCfg().Enabled { server.RpcRegister(v1.NewServiceManagerV1(srvMngr)) @@ -145,7 +146,7 @@ func initLogger(cfg *config.CGRConfig) error { } func initConfigSv1(internalConfigChan chan rpcclient.ClientConnector, - server *utils.Server, anz *services.AnalyzerService) { + server *cores.Server, anz *services.AnalyzerService) { cfgSv1 := v1.NewConfigSv1(cfg) if !cfg.DispatcherSCfg().Enabled { server.RpcRegister(cfgSv1) @@ -157,7 +158,7 @@ func initConfigSv1(internalConfigChan chan rpcclient.ClientConnector, internalConfigChan <- rpc } -func startRPC(server *utils.Server, internalRaterChan, +func startRPC(server *cores.Server, internalRaterChan, internalCdrSChan, internalRsChan, internalStatSChan, internalAttrSChan, internalChargerSChan, internalThdSChan, internalSuplSChan, internalSMGChan, internalAnalyzerSChan, internalDispatcherSChan, @@ -450,15 +451,15 @@ func main() { } utils.Logger.SetLogLevel(lgLevel) // init the concurrentRequests - cncReqsLimit := cfg.GeneralCfg().ConcurrentRequests + cncReqsLimit := cfg.CoreSCfg().Caps if utils.ConcurrentReqsLimit != 0 { // used as shared variable cncReqsLimit = utils.ConcurrentReqsLimit } - cncReqsStrategy := cfg.GeneralCfg().ConcurrentStrategy + cncReqsStrategy := cfg.CoreSCfg().CapsStrategy if len(utils.ConcurrentReqsStrategy) != 0 { cncReqsStrategy = utils.ConcurrentReqsStrategy } - conReqs := utils.NewConReqs(cncReqsLimit, cncReqsStrategy, 0, 0, exitChan) + caps := cores.NewCaps(cncReqsLimit, cncReqsStrategy) utils.Logger.Info(fmt.Sprintf(" starting version <%s><%s>", vers, goVers)) cfg.LazySanityCheck() @@ -539,7 +540,7 @@ func main() { engine.SetFailedPostCacheTTL(cfg.GeneralCfg().FailedPostsTTL) // Rpc/http server - server := utils.NewServer(conReqs) + server := cores.NewServer(caps) if len(cfg.HTTPCfg().DispatchersRegistrarURL) != 0 { server.RegisterHttpFunc(cfg.HTTPCfg().DispatchersRegistrarURL, dispatcherh.Registar) } @@ -571,7 +572,7 @@ func main() { initGuardianSv1(internalGuardianSChan, server, anz) // init CoreSv1 - initCoreSv1(internalCoreSv1Chan, server, anz) + initCoreSv1(internalCoreSv1Chan, server, anz, cfg, caps, exitChan) // Start ServiceManager srvManager := servmanager.NewServiceManager(cfg, exitChan) @@ -603,7 +604,7 @@ func main() { cdrS := services.NewCDRServer(cfg, dmService, storDBService, filterSChan, server, internalCDRServerChan, connManager, anz) - smg := services.NewSessionService(cfg, dmService, server, internalSessionSChan, exitChan, connManager, conReqs, anz) + smg := services.NewSessionService(cfg, dmService, server, internalSessionSChan, exitChan, connManager, caps, anz) ldrs := services.NewLoaderService(cfg, dmService, filterSChan, server, exitChan, internalLoaderSChan, connManager, anz) diff --git a/config/config.go b/config/config.go index 8d90847ad..d0fa3c4a7 100755 --- a/config/config.go +++ b/config/config.go @@ -192,6 +192,7 @@ func NewDefaultCGRConfig() (cfg *CGRConfig, err error) { cfg.sipAgentCfg = new(SIPAgentCfg) cfg.configSCfg = new(ConfigSCfg) cfg.apiBanCfg = new(APIBanCfg) + cfg.coreSCfg = new(CoreSCfg) cfg.ConfigReloads = make(map[string]chan struct{}) @@ -328,8 +329,9 @@ type CGRConfig struct { eesCfg *EEsCfg // EventExporter config rateSCfg *RateSCfg // RateS config sipAgentCfg *SIPAgentCfg // SIPAgent config - configSCfg *ConfigSCfg //ConfigS config + configSCfg *ConfigSCfg // ConfigS config apiBanCfg *APIBanCfg // APIBan config + coreSCfg *CoreSCfg // CoreS config } var posibleLoaderTypes = utils.NewStringSet([]string{utils.MetaAttributes, @@ -739,11 +741,11 @@ func (cfg *CGRConfig) loadAnalyzerCgrCfg(jsnCfg *CgrJsonCfg) (err error) { // loadAPIBanCgrCfg loads the Analyzer section of the configuration func (cfg *CGRConfig) loadAPIBanCgrCfg(jsnCfg *CgrJsonCfg) (err error) { - var jsnAnalyzerCgrCfg *APIBanJsonCfg - if jsnAnalyzerCgrCfg, err = jsnCfg.ApiBanCfgJson(); err != nil { + var jsnAPIBanCfg *APIBanJsonCfg + if jsnAPIBanCfg, err = jsnCfg.ApiBanCfgJson(); err != nil { return } - return cfg.apiBanCfg.loadFromJsonCfg(jsnAnalyzerCgrCfg) + return cfg.apiBanCfg.loadFromJsonCfg(jsnAPIBanCfg) } // loadApierCfg loads the Apier section of the configuration @@ -755,6 +757,15 @@ func (cfg *CGRConfig) loadApierCfg(jsnCfg *CgrJsonCfg) (err error) { return cfg.apier.loadFromJsonCfg(jsnApierCfg) } +// loadCoreSCfg loads the CoreS section of the configuration +func (cfg *CGRConfig) loadCoreSCfg(jsnCfg *CgrJsonCfg) (err error) { + var jsnCoreCfg *CoreSJsonCfg + if jsnCoreCfg, err = jsnCfg.CoreSCfgJson(); err != nil { + return + } + return cfg.coreSCfg.loadFromJSONCfg(jsnCoreCfg) +} + // loadErsCfg loads the Ers section of the configuration func (cfg *CGRConfig) loadErsCfg(jsnCfg *CgrJsonCfg) (err error) { var jsnERsCfg *ERsJsonCfg @@ -1107,13 +1118,20 @@ func (cfg *CGRConfig) ConfigSCfg() *ConfigSCfg { return cfg.configSCfg } -// APIBanCfg reads the Apier configuration +// APIBanCfg reads the ApiBan configuration func (cfg *CGRConfig) APIBanCfg() *APIBanCfg { cfg.lks[APIBanCfgJson].Lock() defer cfg.lks[APIBanCfgJson].Unlock() return cfg.apiBanCfg } +// CoreSCfg reads the CoreS configuration +func (cfg *CGRConfig) CoreSCfg() *CoreSCfg { + cfg.lks[CoreSCfgJson].Lock() + defer cfg.lks[CoreSCfgJson].Unlock() + return cfg.coreSCfg +} + // GetReloadChan returns the reload chanel for the given section func (cfg *CGRConfig) GetReloadChan(sectID string) chan struct{} { return cfg.rldChans[sectID] @@ -1224,6 +1242,8 @@ func (cfg *CGRConfig) V1GetConfigSection(args *SectionWithOpts, reply *map[strin jsonString = utils.ToJSON(cfg.AnalyzerSCfg().AsMapInterface()) case RateSJson: jsonString = utils.ToJSON(cfg.RateSCfg().AsMapInterface()) + case CoreSCfgJson: + jsonString = utils.ToJSON(cfg.CoreSCfg().AsMapInterface()) default: return errors.New("Invalid section") } @@ -1353,6 +1373,7 @@ func (cfg *CGRConfig) getLoadFunctions() map[string]func(*CgrJsonCfg) error { TemplatesJson: cfg.loadTemplateSCfg, ConfigSJson: cfg.loadConfigSCfg, APIBanCfgJson: cfg.loadAPIBanCgrCfg, + CoreSCfgJson: cfg.loadCoreSCfg, } } @@ -1581,6 +1602,7 @@ func (cfg *CGRConfig) reloadSections(sections ...string) (err error) { case LISTEN_JSN: case TlsCfgJson: // nothing to reload case APIBanCfgJson: // nothing to reload + case CoreSCfgJson: // nothing to reload case HTTP_JSN: cfg.rldChans[HTTP_JSN] <- struct{}{} case SCHEDULER_JSN: @@ -1689,6 +1711,7 @@ func (cfg *CGRConfig) AsMapInterface(separator string) (mp map[string]interface{ SIPAgentJson: cfg.sipAgentCfg.AsMapInterface(separator), TemplatesJson: cfg.templates.AsMapInterface(separator), ConfigSJson: cfg.configSCfg.AsMapInterface(), + CoreSCfgJson: cfg.coreSCfg.AsMapInterface(), }, nil } @@ -1816,6 +1839,8 @@ func (cfg *CGRConfig) V1GetConfigSectionString(args *SectionWithOpts, reply *str *reply = utils.ToJSON(cfg.AnalyzerSCfg().AsMapInterface()) case RateSJson: *reply = utils.ToJSON(cfg.RateSCfg().AsMapInterface()) + case CoreSCfgJson: + *reply = utils.ToJSON(cfg.CoreSCfg().AsMapInterface()) default: return errors.New("Invalid section") } diff --git a/config/config_defaults.go b/config/config_defaults.go index 26d62af89..041210f8f 100755 --- a/config/config_defaults.go +++ b/config/config_defaults.go @@ -53,8 +53,13 @@ const CGRATES_CFG_JSON = ` "digest_equal": ":", // equal symbol used in case of digests "rsr_separator": ";", // separator used within RSR fields "max_parallel_conns": 100, // the maximum number of connection used by the *parallel strategy - "concurrent_requests": 0, // maximum concurrent request allowed ( 0 to disabled ) - "concurrent_strategy": "*busy", // strategy in case in case of concurrent requests reached +}, + + +"cores": { + "caps": 0, // maximum concurrent request allowed ( 0 to disabled ) + "caps_strategy": "*busy", // strategy in case in case of concurrent requests reached + "caps_stats_interval": "0" // the interval we sample for caps stats ( 0 to disabled ) }, @@ -267,6 +272,7 @@ const CGRATES_CFG_JSON = ` "*uch": {"limit": -1, "ttl": "3h", "static_ttl": false, "replicate": false}, // User cache "*stir": {"limit": -1, "ttl": "3h", "static_ttl": false, "replicate": false}, // stirShaken cache keys "*apiban":{"limit": -1, "ttl": "2m", "static_ttl": false, "replicate": false}, + "*caps_events": {"limit": -1, "ttl": "", "static_ttl": false, "replicate": false}, // caps cached samples // only for *internal database "*versions": {"limit": -1, "ttl": "", "static_ttl": false, "replicate": false}, // for version storing diff --git a/config/config_json.go b/config/config_json.go index 74738e669..ab9d3a999 100644 --- a/config/config_json.go +++ b/config/config_json.go @@ -65,6 +65,7 @@ const ( TemplatesJson = "templates" ConfigSJson = "configs" APIBanCfgJson = "apiban" + CoreSCfgJson = "cores" ) var ( @@ -72,7 +73,7 @@ var ( CACHE_JSN, FilterSjsn, RALS_JSN, CDRS_JSN, ERsJson, SessionSJson, AsteriskAgentJSN, FreeSWITCHAgentJSN, KamailioAgentJSN, DA_JSN, RA_JSN, HttpAgentJson, DNSAgentJson, ATTRIBUTE_JSN, ChargerSCfgJson, RESOURCES_JSON, STATS_JSON, THRESHOLDS_JSON, RouteSJson, LoaderJson, MAILER_JSN, SURETAX_JSON, CgrLoaderCfgJson, CgrMigratorCfgJson, DispatcherSJson, - AnalyzerCfgJson, ApierS, EEsJson, RateSJson, SIPAgentJson, DispatcherHJson, TemplatesJson, ConfigSJson, APIBanCfgJson} + AnalyzerCfgJson, ApierS, EEsJson, RateSJson, SIPAgentJson, DispatcherHJson, TemplatesJson, ConfigSJson, APIBanCfgJson, CoreSCfgJson} ) // Loads the json config out of io.Reader, eg other sources than file, maybe over http @@ -570,3 +571,15 @@ func (self CgrJsonCfg) ApiBanCfgJson() (*APIBanJsonCfg, error) { } return cfg, nil } + +func (self CgrJsonCfg) CoreSCfgJson() (*CoreSJsonCfg, error) { + rawCfg, hasKey := self[CoreSCfgJson] + if !hasKey { + return nil, nil + } + cfg := new(CoreSJsonCfg) + if err := json.Unmarshal(*rawCfg, cfg); err != nil { + return nil, err + } + return cfg, nil +} diff --git a/config/config_json_test.go b/config/config_json_test.go index bf67b85c9..43636adca 100755 --- a/config/config_json_test.go +++ b/config/config_json_test.go @@ -63,8 +63,6 @@ func TestDfGeneralJsonCfg(t *testing.T) { Digest_equal: utils.StringPointer(":"), Rsr_separator: utils.StringPointer(";"), Max_parallel_conns: utils.IntPointer(100), - Concurrent_requests: utils.IntPointer(0), - Concurrent_strategy: utils.StringPointer(utils.MetaBusy), } if gCfg, err := dfCgrJSONCfg.GeneralJsonCfg(); err != nil { t.Error(err) @@ -72,6 +70,18 @@ func TestDfGeneralJsonCfg(t *testing.T) { t.Errorf("expecting: %s, \nreceived: %s", utils.ToIJSON(eCfg), utils.ToIJSON(gCfg)) } } +func TestDfCoreSJsonCfg(t *testing.T) { + eCfg := &CoreSJsonCfg{ + Caps: utils.IntPointer(0), + Caps_strategy: utils.StringPointer(utils.MetaBusy), + Caps_stats_interval: utils.StringPointer("0"), + } + if gCfg, err := dfCgrJSONCfg.CoreSCfgJson(); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eCfg, gCfg) { + t.Errorf("expecting: %s, \nreceived: %s", utils.ToIJSON(eCfg), utils.ToIJSON(gCfg)) + } +} func TestCacheJsonCfg(t *testing.T) { eCfg := &CacheJsonCfg{ @@ -214,6 +224,10 @@ func TestCacheJsonCfg(t *testing.T) { utils.CacheSTIR: {Limit: utils.IntPointer(-1), Ttl: utils.StringPointer("3h"), Static_ttl: utils.BoolPointer(false), Replicate: utils.BoolPointer(false)}, + utils.CacheCapsEvents: {Limit: utils.IntPointer(-1), + Ttl: utils.StringPointer(""), Static_ttl: utils.BoolPointer(false), + Replicate: utils.BoolPointer(false), + }, utils.CacheVersions: {Limit: utils.IntPointer(-1), Ttl: utils.StringPointer(""), Static_ttl: utils.BoolPointer(false), diff --git a/config/config_test.go b/config/config_test.go index 24fa2b336..8923acfaf 100755 --- a/config/config_test.go +++ b/config/config_test.go @@ -589,6 +589,7 @@ func TestCgrCfgJSONDefaultsCacheCFG(t *testing.T) { TTL: 3 * time.Hour, StaticTTL: false}, utils.CacheSTIR: {Limit: -1, TTL: 3 * time.Hour, StaticTTL: false}, + utils.CacheCapsEvents: {Limit: -1}, utils.CacheVersions: {Limit: -1, TTL: 0, StaticTTL: false, Precache: false}, diff --git a/config/corescfg.go b/config/corescfg.go new file mode 100644 index 000000000..83c5d9c9a --- /dev/null +++ b/config/corescfg.go @@ -0,0 +1,63 @@ +/* +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 config + +import ( + "time" + + "github.com/cgrates/cgrates/utils" +) + +// CoreSCfg the config for the coreS +type CoreSCfg struct { + Caps int + CapsStrategy string + CapsStatsInterval time.Duration +} + +func (cS *CoreSCfg) loadFromJSONCfg(jsnCfg *CoreSJsonCfg) (err error) { + if jsnCfg == nil { + return + } + if jsnCfg.Caps != nil { + cS.Caps = *jsnCfg.Caps + } + if jsnCfg.Caps_strategy != nil { + cS.CapsStrategy = *jsnCfg.Caps_strategy + } + if jsnCfg.Caps_stats_interval != nil { + if cS.CapsStatsInterval, err = utils.ParseDurationWithNanosecs(*jsnCfg.Caps_stats_interval); err != nil { + return + } + } + return +} + +// AsMapInterface returns the config as a map[string]interface{} +func (cS *CoreSCfg) AsMapInterface() map[string]interface{} { + mp := map[string]interface{}{ + utils.CapsCfg: cS.Caps, + utils.CapsStrategyCfg: cS.CapsStrategy, + utils.CapsStatsIntervalCfg: cS.CapsStatsInterval.String(), + } + if cS.CapsStatsInterval == 0 { + mp[utils.CapsStatsIntervalCfg] = "0" + } + return mp +} diff --git a/config/corescfg_test.go b/config/corescfg_test.go new file mode 100644 index 000000000..eed25a51c --- /dev/null +++ b/config/corescfg_test.go @@ -0,0 +1,104 @@ +/* +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 config + +import ( + "reflect" + "testing" + "time" + + "github.com/cgrates/cgrates/utils" +) + +func TestCoreSloadFromJsonCfg(t *testing.T) { + var alS, expected CoreSCfg + if err := alS.loadFromJSONCfg(nil); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(alS, expected) { + t.Errorf("Expected: %+v ,received: %+v", expected, alS) + } + if err := alS.loadFromJSONCfg(new(CoreSJsonCfg)); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(alS, expected) { + t.Errorf("Expected: %+v ,received: %+v", expected, alS) + } + cfgJSONStr := `{ + "cores": { + "caps": 0, // maximum concurrent request allowed ( 0 to disabled ) + "caps_strategy": "*busy", // strategy in case in case of concurrent requests reached + "caps_stats_interval": "0" // the interval we sample for caps stats ( 0 to disabled ) + }, +}` + expected = CoreSCfg{ + Caps: 0, + CapsStrategy: utils.MetaBusy, + CapsStatsInterval: 0, + } + if jsnCfg, err := NewCgrJsonCfgFromBytes([]byte(cfgJSONStr)); err != nil { + t.Error(err) + } else if jsnalS, err := jsnCfg.CoreSCfgJson(); err != nil { + t.Error(err) + } else if err = alS.loadFromJSONCfg(jsnalS); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(expected, alS) { + t.Errorf("Expected: %+v , received: %+v", expected, alS) + } + + expErr := "time: unknown unit \"ss\" in duration \"1ss\"" + coresJSONCfg := &CoreSJsonCfg{ + Caps_stats_interval: utils.StringPointer("1ss"), + } + if err = alS.loadFromJSONCfg(coresJSONCfg); err == nil || err.Error() != expErr { + t.Errorf("Expected error: %s,received: %v", expErr, err) + } +} + +func TestCoreSAsMapInterface(t *testing.T) { + var alS CoreSCfg + cfgJSONStr := `{ + "cores": { + "caps": 0, // maximum concurrent request allowed ( 0 to disabled ) + "caps_strategy": "*busy", // strategy in case in case of concurrent requests reached + "caps_stats_interval": "0s" // the interval we sample for caps stats ( 0 to disabled ) + }, +}` + eMap := map[string]interface{}{ + utils.CapsCfg: 0, + utils.CapsStrategyCfg: utils.MetaBusy, + utils.CapsStatsIntervalCfg: "0", + } + if jsnCfg, err := NewCgrJsonCfgFromBytes([]byte(cfgJSONStr)); err != nil { + t.Error(err) + } else if jsnalS, err := jsnCfg.CoreSCfgJson(); err != nil { + t.Error(err) + } else if err = alS.loadFromJSONCfg(jsnalS); err != nil { + t.Error(err) + } else if rcv := alS.AsMapInterface(); !reflect.DeepEqual(eMap, rcv) { + t.Errorf("\nExpected: %+v\nReceived: %+v", utils.ToJSON(eMap), utils.ToJSON(rcv)) + } + eMap[utils.CapsStatsIntervalCfg] = "1s" + alS = CoreSCfg{ + Caps: 0, + CapsStatsInterval: time.Second, + CapsStrategy: utils.MetaBusy, + } + if rcv := alS.AsMapInterface(); !reflect.DeepEqual(eMap, rcv) { + t.Errorf("\nExpected: %+v\nReceived: %+v", utils.ToJSON(eMap), utils.ToJSON(rcv)) + } +} diff --git a/config/datadbcfg.go b/config/datadbcfg.go index 807ce23ed..72170f994 100644 --- a/config/datadbcfg.go +++ b/config/datadbcfg.go @@ -173,7 +173,7 @@ func (itm *ItemOpt) AsMapInterface() (initialMP map[string]interface{}) { utils.ReplicateCfg: itm.Replicate, } if itm.APIKey != utils.EmptyString { - initialMP[utils.ApiKeyCfg] = itm.APIKey + initialMP[utils.APIKeyCfg] = itm.APIKey } if itm.RouteID != utils.EmptyString { initialMP[utils.RouteIDCfg] = itm.RouteID diff --git a/config/datadbcfg_test.go b/config/datadbcfg_test.go index b52a076ed..7b4cc2fbc 100644 --- a/config/datadbcfg_test.go +++ b/config/datadbcfg_test.go @@ -506,8 +506,8 @@ func TestDataDbCfgAsMapInterface(t *testing.T) { utils.RemoteConnsCfg: []string{}, utils.ReplicationConnsCfg: []string{}, utils.ItemsCfg: map[string]interface{}{ - utils.MetaAccounts: map[string]interface{}{utils.RemoteCfg: true, utils.ReplicateCfg: false, utils.ApiKeyCfg: "randomVal", utils.RouteIDCfg: "randomVal"}, - utils.MetaReverseDestinations: map[string]interface{}{utils.RemoteCfg: false, utils.ReplicateCfg: false, utils.ApiKeyCfg: "randomVal", utils.RouteIDCfg: "randomVal"}, + utils.MetaAccounts: map[string]interface{}{utils.RemoteCfg: true, utils.ReplicateCfg: false, utils.APIKeyCfg: "randomVal", utils.RouteIDCfg: "randomVal"}, + utils.MetaReverseDestinations: map[string]interface{}{utils.RemoteCfg: false, utils.ReplicateCfg: false, utils.APIKeyCfg: "randomVal", utils.RouteIDCfg: "randomVal"}, }, } if cgrCfg, err := NewCGRConfigFromJSONStringWithDefaults(cfgJSONStr); err != nil { diff --git a/config/diametercfg.go b/config/diametercfg.go index 43f2c2fbd..dbb56ffa7 100644 --- a/config/diametercfg.go +++ b/config/diametercfg.go @@ -120,19 +120,19 @@ func (da *DiameterAgentCfg) loadFromJsonCfg(jsnCfg *DiameterAgentJsonCfg, separa func (ds *DiameterAgentCfg) AsMapInterface(separator string) (initialMP map[string]interface{}) { initialMP = map[string]interface{}{ - utils.EnabledCfg: ds.Enabled, - utils.ListenNetCfg: ds.ListenNet, - utils.ListenCfg: ds.Listen, - utils.DictionariesPathCfg: ds.DictionariesPath, - utils.OriginHostCfg: ds.OriginHost, - utils.OriginRealmCfg: ds.OriginRealm, - utils.VendorIdCfg: ds.VendorId, - utils.ProductNameCfg: ds.ProductName, - utils.ConcurrentReqsCfg: ds.ConcurrentReqs, - utils.SyncedConnReqsCfg: ds.SyncedConnReqs, - utils.ASRTemplateCfg: ds.ASRTemplate, - utils.RARTemplateCfg: ds.RARTemplate, - utils.ForcedDisconnectCfg: ds.ForcedDisconnect, + utils.EnabledCfg: ds.Enabled, + utils.ListenNetCfg: ds.ListenNet, + utils.ListenCfg: ds.Listen, + utils.DictionariesPathCfg: ds.DictionariesPath, + utils.OriginHostCfg: ds.OriginHost, + utils.OriginRealmCfg: ds.OriginRealm, + utils.VendorIDCfg: ds.VendorId, + utils.ProductNameCfg: ds.ProductName, + utils.ConcurrentRequestsCfg: ds.ConcurrentReqs, + utils.SyncedConnReqsCfg: ds.SyncedConnReqs, + utils.ASRTemplateCfg: ds.ASRTemplate, + utils.RARTemplateCfg: ds.RARTemplate, + utils.ForcedDisconnectCfg: ds.ForcedDisconnect, } requestProcessors := make([]map[string]interface{}, len(ds.RequestProcessors)) diff --git a/config/diametercfg_test.go b/config/diametercfg_test.go index 64dae5e50..9df4d0d3b 100644 --- a/config/diametercfg_test.go +++ b/config/diametercfg_test.go @@ -161,10 +161,10 @@ func TestDiameterAgentCfgAsMapInterface(t *testing.T) { utils.RARTemplateCfg: "", utils.SessionSConnsCfg: []string{utils.MetaInternal, "*conn1"}, utils.SyncedConnReqsCfg: true, - utils.VendorIdCfg: 0, + utils.VendorIDCfg: 0, utils.RequestProcessorsCfg: []map[string]interface{}{ { - utils.IdCfg: utils.CGRATES, + utils.IDCfg: utils.CGRATES, utils.TenantCfg: "1", utils.FiltersCfg: []string{}, utils.FlagsCfg: []string{"1"}, @@ -224,7 +224,7 @@ func TestDiameterAgentCfgAsMapInterface1(t *testing.T) { utils.RARTemplateCfg: "", utils.SessionSConnsCfg: []string{"*internal"}, utils.SyncedConnReqsCfg: false, - utils.VendorIdCfg: 0, + utils.VendorIDCfg: 0, utils.RequestProcessorsCfg: []map[string]interface{}{}, } if cgrCfg, err := NewCGRConfigFromJSONStringWithDefaults(cfgJSONStr); err != nil { diff --git a/config/dispatcherhcfg_test.go b/config/dispatcherhcfg_test.go index 9389e88ab..737ac7ccf 100644 --- a/config/dispatcherhcfg_test.go +++ b/config/dispatcherhcfg_test.go @@ -122,12 +122,12 @@ func TestDispatcherHCfgAsMapInterface(t *testing.T) { utils.HostsCfg: map[string][]map[string]interface{}{ utils.MetaDefault: { { - utils.IdCfg: "Host1", + utils.IDCfg: "Host1", utils.RegisterTransportCfg: "*json", utils.RegisterTLSCfg: false, }, { - utils.IdCfg: "Host2", + utils.IDCfg: "Host2", utils.RegisterTransportCfg: "*gob", utils.RegisterTLSCfg: false, }, @@ -200,10 +200,10 @@ func TestDispatcherHCfgAsMapInterface1(t *testing.T) { t.Error(err) } else { rcv := cgrCfg.dispatcherHCfg.AsMapInterface() - if !reflect.DeepEqual(eMap[utils.HostsCfg].(map[string][]map[string]interface{})[utils.IdCfg], - rcv[utils.HostsCfg].(map[string][]map[string]interface{})[utils.IdCfg]) { - t.Errorf("Expected %+v, received %+v", eMap[utils.HostsCfg].(map[string][]map[string]interface{})[utils.IdCfg], - rcv[utils.HostsCfg].(map[string][]map[string]interface{})[utils.IdCfg]) + if !reflect.DeepEqual(eMap[utils.HostsCfg].(map[string][]map[string]interface{})[utils.IDCfg], + rcv[utils.HostsCfg].(map[string][]map[string]interface{})[utils.IDCfg]) { + t.Errorf("Expected %+v, received %+v", eMap[utils.HostsCfg].(map[string][]map[string]interface{})[utils.IDCfg], + rcv[utils.HostsCfg].(map[string][]map[string]interface{})[utils.IDCfg]) } else if !reflect.DeepEqual(eMap[utils.HostsCfg], rcv[utils.HostsCfg]) { t.Errorf("Expected %+v, received %+v", eMap[utils.HostsCfg], rcv[utils.HostsCfg]) } else if !reflect.DeepEqual(eMap, rcv) { diff --git a/config/dnsagentcfg_test.go b/config/dnsagentcfg_test.go index 991bae848..8a8ed23bf 100644 --- a/config/dnsagentcfg_test.go +++ b/config/dnsagentcfg_test.go @@ -254,7 +254,7 @@ func TestDNSAgentCfgAsMapInterface1(t *testing.T) { utils.TimezoneCfg: "UTC", utils.RequestProcessorsCfg: []map[string]interface{}{ { - utils.IdCfg: "OutboundAUTHDryRun", + utils.IDCfg: "OutboundAUTHDryRun", utils.FiltersCfg: []string{"*string:~*req.request_type:OutboundAUTH", "*string:~*req.Msisdn:497700056231"}, utils.TenantCfg: "cgrates.org", utils.FlagsCfg: []string{"*dryrun"}, diff --git a/config/eescfg_test.go b/config/eescfg_test.go index 82aa25407..ed0da2bfa 100644 --- a/config/eescfg_test.go +++ b/config/eescfg_test.go @@ -678,7 +678,7 @@ func TestEEsCfgAsMapInterface(t *testing.T) { }, utils.ExportersCfg: []map[string]interface{}{ { - utils.IdCfg: "CSVExporter", + utils.IDCfg: "CSVExporter", utils.TypeCfg: "*file_csv", utils.ExportPathCfg: "/tmp/testCSV", utils.OptsCfg: map[string]interface{}{}, diff --git a/config/erscfg.go b/config/erscfg.go index cc61bdba4..83e741537 100644 --- a/config/erscfg.go +++ b/config/erscfg.go @@ -282,7 +282,7 @@ func (er *EventReaderCfg) AsMapInterface(separator string) (initialMP map[string utils.RowLengthCfg: er.RowLength, utils.FieldSepCfg: er.FieldSep, utils.HeaderDefCharCfg: er.HeaderDefineChar, - utils.ConcurrentReqsCfg: er.ConcurrentReqs, + utils.ConcurrentRequestsCfg: er.ConcurrentReqs, utils.SourcePathCfg: er.SourcePath, utils.ProcessedPathCfg: er.ProcessedPath, utils.TimezoneCfg: er.Timezone, diff --git a/config/erscfg_test.go b/config/erscfg_test.go index 125882d44..10e16cce2 100644 --- a/config/erscfg_test.go +++ b/config/erscfg_test.go @@ -833,7 +833,7 @@ func TestERsCfgAsMapInterfaceCase1(t *testing.T) { { utils.FiltersCfg: []string{}, utils.FlagsCfg: []string{}, - utils.IdCfg: "*default", + utils.IDCfg: "*default", utils.PartialRecordCacheCfg: "0", utils.ProcessedPathCfg: "/var/spool/cgrates/ers/out", utils.RowLengthCfg: 0, @@ -937,7 +937,7 @@ func TestERSCfgAsMapInterfaceCase2(t *testing.T) { { utils.FiltersCfg: []string{}, utils.FlagsCfg: []string{}, - utils.IdCfg: "*default", + utils.IDCfg: "*default", utils.PartialRecordCacheCfg: "0", utils.ProcessedPathCfg: "/var/spool/cgrates/ers/out", utils.RowLengthCfg: 0, diff --git a/config/generalcfg.go b/config/generalcfg.go index cf016af52..52dc40949 100644 --- a/config/generalcfg.go +++ b/config/generalcfg.go @@ -27,33 +27,31 @@ import ( // General config section type GeneralCfg struct { - NodeID string // Identifier for this engine instance - Logger string // dictates the way logs are displayed/stored - LogLevel int // system wide log level, nothing higher than this will be logged - RoundingDecimals int // Number of decimals to round end prices at - DBDataEncoding string // The encoding used to store object data in strings: - TpExportPath string // Path towards export folder for offline Tariff Plans - PosterAttempts int // Time to wait before writing the failed posts in a single file - FailedPostsDir string // Directory path where we store failed http requests - FailedPostsTTL time.Duration // Directory path where we store failed http requests - DefaultReqType string // Use this request type if not defined on top - DefaultCategory string // set default type of record - DefaultTenant string // set default tenant - DefaultTimezone string // default timezone for timestamps where not specified <""|UTC|Local|$IANA_TZ_DB> - DefaultCaching string - ConnectAttempts int // number of initial connection attempts before giving up - Reconnects int // number of recconect attempts in case of connection lost <-1 for infinite | nb> - ConnectTimeout time.Duration // timeout for RPC connection attempts - ReplyTimeout time.Duration // timeout replies if not reaching back - LockingTimeout time.Duration // locking mechanism timeout to avoid deadlocks - MinCallDuration time.Duration - MaxCallDuration time.Duration - DigestSeparator string // - DigestEqual string // - RSRSep string // separator used to split RSRParser (by default is used ";") - MaxParallelConns int // the maximum number of connection used by the *parallel strategy - ConcurrentRequests int - ConcurrentStrategy string + NodeID string // Identifier for this engine instance + Logger string // dictates the way logs are displayed/stored + LogLevel int // system wide log level, nothing higher than this will be logged + RoundingDecimals int // Number of decimals to round end prices at + DBDataEncoding string // The encoding used to store object data in strings: + TpExportPath string // Path towards export folder for offline Tariff Plans + PosterAttempts int // Time to wait before writing the failed posts in a single file + FailedPostsDir string // Directory path where we store failed http requests + FailedPostsTTL time.Duration // Directory path where we store failed http requests + DefaultReqType string // Use this request type if not defined on top + DefaultCategory string // set default type of record + DefaultTenant string // set default tenant + DefaultTimezone string // default timezone for timestamps where not specified <""|UTC|Local|$IANA_TZ_DB> + DefaultCaching string + ConnectAttempts int // number of initial connection attempts before giving up + Reconnects int // number of recconect attempts in case of connection lost <-1 for infinite | nb> + ConnectTimeout time.Duration // timeout for RPC connection attempts + ReplyTimeout time.Duration // timeout replies if not reaching back + LockingTimeout time.Duration // locking mechanism timeout to avoid deadlocks + MinCallDuration time.Duration + MaxCallDuration time.Duration + DigestSeparator string // + DigestEqual string // + RSRSep string // separator used to split RSRParser (by default is used ";") + MaxParallelConns int // the maximum number of connection used by the *parallel strategy } //loadFromJsonCfg loads General config from JsonCfg @@ -149,39 +147,31 @@ func (gencfg *GeneralCfg) loadFromJsonCfg(jsnGeneralCfg *GeneralJsonCfg) (err er if jsnGeneralCfg.Max_parallel_conns != nil { gencfg.MaxParallelConns = *jsnGeneralCfg.Max_parallel_conns } - if jsnGeneralCfg.Concurrent_requests != nil { - gencfg.ConcurrentRequests = *jsnGeneralCfg.Concurrent_requests - } - if jsnGeneralCfg.Concurrent_strategy != nil { - gencfg.ConcurrentStrategy = *jsnGeneralCfg.Concurrent_strategy - } return nil } func (gencfg *GeneralCfg) AsMapInterface() (initialMP map[string]interface{}) { initialMP = map[string]interface{}{ - utils.NodeIDCfg: gencfg.NodeID, - utils.LoggerCfg: gencfg.Logger, - utils.LogLevelCfg: gencfg.LogLevel, - utils.RoundingDecimalsCfg: gencfg.RoundingDecimals, - utils.DBDataEncodingCfg: utils.Meta + gencfg.DBDataEncoding, - utils.TpExportPathCfg: gencfg.TpExportPath, - utils.PosterAttemptsCfg: gencfg.PosterAttempts, - utils.FailedPostsDirCfg: gencfg.FailedPostsDir, - utils.DefaultReqTypeCfg: gencfg.DefaultReqType, - utils.DefaultCategoryCfg: gencfg.DefaultCategory, - utils.DefaultTenantCfg: gencfg.DefaultTenant, - utils.DefaultTimezoneCfg: gencfg.DefaultTimezone, - utils.DefaultCachingCfg: gencfg.DefaultCaching, - utils.ConnectAttemptsCfg: gencfg.ConnectAttempts, - utils.ReconnectsCfg: gencfg.Reconnects, - utils.DigestSeparatorCfg: gencfg.DigestSeparator, - utils.DigestEqualCfg: gencfg.DigestEqual, - utils.RSRSepCfg: gencfg.RSRSep, - utils.MaxParallelConnsCfg: gencfg.MaxParallelConns, - utils.ConcurrentRequestsCfg: gencfg.ConcurrentRequests, - utils.ConcurrentStrategyCfg: gencfg.ConcurrentStrategy, + utils.NodeIDCfg: gencfg.NodeID, + utils.LoggerCfg: gencfg.Logger, + utils.LogLevelCfg: gencfg.LogLevel, + utils.RoundingDecimalsCfg: gencfg.RoundingDecimals, + utils.DBDataEncodingCfg: utils.Meta + gencfg.DBDataEncoding, + utils.TpExportPathCfg: gencfg.TpExportPath, + utils.PosterAttemptsCfg: gencfg.PosterAttempts, + utils.FailedPostsDirCfg: gencfg.FailedPostsDir, + utils.DefaultReqTypeCfg: gencfg.DefaultReqType, + utils.DefaultCategoryCfg: gencfg.DefaultCategory, + utils.DefaultTenantCfg: gencfg.DefaultTenant, + utils.DefaultTimezoneCfg: gencfg.DefaultTimezone, + utils.DefaultCachingCfg: gencfg.DefaultCaching, + utils.ConnectAttemptsCfg: gencfg.ConnectAttempts, + utils.ReconnectsCfg: gencfg.Reconnects, + utils.DigestSeparatorCfg: gencfg.DigestSeparator, + utils.DigestEqualCfg: gencfg.DigestEqual, + utils.RSRSepCfg: gencfg.RSRSep, + utils.MaxParallelConnsCfg: gencfg.MaxParallelConns, } if gencfg.LockingTimeout != 0 { diff --git a/config/generalcfg_test.go b/config/generalcfg_test.go index d9e432038..5047c9e8f 100644 --- a/config/generalcfg_test.go +++ b/config/generalcfg_test.go @@ -49,31 +49,30 @@ func TestGeneralCfgloadFromJsonCfg(t *testing.T) { } expected := &GeneralCfg{ - NodeID: "randomID", - Logger: utils.MetaSysLog, - LogLevel: 6, - RoundingDecimals: 5, - DBDataEncoding: "msgpack", - TpExportPath: "/var/spool/cgrates/tpe", - PosterAttempts: 3, - FailedPostsDir: "/var/spool/cgrates/failed_posts", - DefaultReqType: utils.META_RATED, - DefaultCategory: utils.CALL, - DefaultTenant: "cgrates.org", - DefaultTimezone: "Local", - ConnectAttempts: 3, - Reconnects: -1, - ConnectTimeout: time.Second, - ReplyTimeout: 2 * time.Second, - MinCallDuration: 0, - MaxCallDuration: 3 * time.Hour, - DigestSeparator: ",", - DigestEqual: ":", - ConcurrentStrategy: utils.MetaBusy, - MaxParallelConns: 100, - RSRSep: ";", - DefaultCaching: utils.MetaReload, - FailedPostsTTL: 2, + NodeID: "randomID", + Logger: utils.MetaSysLog, + LogLevel: 6, + RoundingDecimals: 5, + DBDataEncoding: "msgpack", + TpExportPath: "/var/spool/cgrates/tpe", + PosterAttempts: 3, + FailedPostsDir: "/var/spool/cgrates/failed_posts", + DefaultReqType: utils.META_RATED, + DefaultCategory: utils.CALL, + DefaultTenant: "cgrates.org", + DefaultTimezone: "Local", + ConnectAttempts: 3, + Reconnects: -1, + ConnectTimeout: time.Second, + ReplyTimeout: 2 * time.Second, + MinCallDuration: 0, + MaxCallDuration: 3 * time.Hour, + DigestSeparator: ",", + DigestEqual: ":", + MaxParallelConns: 100, + RSRSep: ";", + DefaultCaching: utils.MetaReload, + FailedPostsTTL: 2, } if jsnCfg, err := NewDefaultCGRConfig(); err != nil { t.Error(err) @@ -171,33 +170,31 @@ func TestGeneralCfgAsMapInterface(t *testing.T) { }, }` eMap := map[string]interface{}{ - utils.NodeIDCfg: "cgrates", - utils.LoggerCfg: "*syslog", - utils.LogLevelCfg: 6, - utils.RoundingDecimalsCfg: 5, - utils.DBDataEncodingCfg: "*msgpack", - utils.TpExportPathCfg: "/var/spool/cgrates/tpe", - utils.PosterAttemptsCfg: 3, - utils.FailedPostsDirCfg: "/var/spool/cgrates/failed_posts", - utils.FailedPostsTTLCfg: "5s", - utils.DefaultReqTypeCfg: "*rated", - utils.DefaultCategoryCfg: "call", - utils.DefaultTenantCfg: "cgrates.org", - utils.DefaultTimezoneCfg: "Local", - utils.DefaultCachingCfg: "*reload", - utils.ConnectAttemptsCfg: 5, - utils.ReconnectsCfg: -1, - utils.MinCallDurationCfg: "0", - utils.MaxCallDurationCfg: "3h0m0s", - utils.ConnectTimeoutCfg: "1s", - utils.ReplyTimeoutCfg: "2s", - utils.LockingTimeoutCfg: "1s", - utils.DigestSeparatorCfg: ",", - utils.DigestEqualCfg: ":", - utils.RSRSepCfg: ";", - utils.MaxParallelConnsCfg: 100, - utils.ConcurrentRequestsCfg: 0, - utils.ConcurrentStrategyCfg: utils.MetaBusy, + utils.NodeIDCfg: "cgrates", + utils.LoggerCfg: "*syslog", + utils.LogLevelCfg: 6, + utils.RoundingDecimalsCfg: 5, + utils.DBDataEncodingCfg: "*msgpack", + utils.TpExportPathCfg: "/var/spool/cgrates/tpe", + utils.PosterAttemptsCfg: 3, + utils.FailedPostsDirCfg: "/var/spool/cgrates/failed_posts", + utils.FailedPostsTTLCfg: "5s", + utils.DefaultReqTypeCfg: "*rated", + utils.DefaultCategoryCfg: "call", + utils.DefaultTenantCfg: "cgrates.org", + utils.DefaultTimezoneCfg: "Local", + utils.DefaultCachingCfg: "*reload", + utils.ConnectAttemptsCfg: 5, + utils.ReconnectsCfg: -1, + utils.MinCallDurationCfg: "0", + utils.MaxCallDurationCfg: "3h0m0s", + utils.ConnectTimeoutCfg: "1s", + utils.ReplyTimeoutCfg: "2s", + utils.LockingTimeoutCfg: "1s", + utils.DigestSeparatorCfg: ",", + utils.DigestEqualCfg: ":", + utils.RSRSepCfg: ";", + utils.MaxParallelConnsCfg: 100, } if cgrCfg, err := NewCGRConfigFromJSONStringWithDefaults(cfgJSONStr); err != nil { t.Error(err) @@ -219,33 +216,31 @@ func TestGeneralCfgAsMapInterface1(t *testing.T) { } }` eMap := map[string]interface{}{ - utils.NodeIDCfg: "ENGINE1", - utils.LoggerCfg: "*syslog", - utils.LogLevelCfg: 6, - utils.RoundingDecimalsCfg: 5, - utils.DBDataEncodingCfg: "*msgpack", - utils.TpExportPathCfg: "/var/spool/cgrates/tpe", - utils.PosterAttemptsCfg: 3, - utils.FailedPostsDirCfg: "/var/spool/cgrates/failed_posts", - utils.FailedPostsTTLCfg: "0", - utils.DefaultReqTypeCfg: "*rated", - utils.DefaultCategoryCfg: "call", - utils.DefaultTenantCfg: "cgrates.org", - utils.DefaultTimezoneCfg: "Local", - utils.DefaultCachingCfg: "*reload", - utils.ConnectAttemptsCfg: 5, - utils.ReconnectsCfg: -1, - utils.ConnectTimeoutCfg: "0", - utils.ReplyTimeoutCfg: "0", - utils.LockingTimeoutCfg: "0", - utils.MinCallDurationCfg: "1s", - utils.MaxCallDurationCfg: "0", - utils.DigestSeparatorCfg: ",", - utils.DigestEqualCfg: ":", - utils.RSRSepCfg: ";", - utils.MaxParallelConnsCfg: 100, - utils.ConcurrentRequestsCfg: 0, - utils.ConcurrentStrategyCfg: utils.MetaBusy, + utils.NodeIDCfg: "ENGINE1", + utils.LoggerCfg: "*syslog", + utils.LogLevelCfg: 6, + utils.RoundingDecimalsCfg: 5, + utils.DBDataEncodingCfg: "*msgpack", + utils.TpExportPathCfg: "/var/spool/cgrates/tpe", + utils.PosterAttemptsCfg: 3, + utils.FailedPostsDirCfg: "/var/spool/cgrates/failed_posts", + utils.FailedPostsTTLCfg: "0", + utils.DefaultReqTypeCfg: "*rated", + utils.DefaultCategoryCfg: "call", + utils.DefaultTenantCfg: "cgrates.org", + utils.DefaultTimezoneCfg: "Local", + utils.DefaultCachingCfg: "*reload", + utils.ConnectAttemptsCfg: 5, + utils.ReconnectsCfg: -1, + utils.ConnectTimeoutCfg: "0", + utils.ReplyTimeoutCfg: "0", + utils.LockingTimeoutCfg: "0", + utils.MinCallDurationCfg: "1s", + utils.MaxCallDurationCfg: "0", + utils.DigestSeparatorCfg: ",", + utils.DigestEqualCfg: ":", + utils.RSRSepCfg: ";", + utils.MaxParallelConnsCfg: 100, } if cgrCfg, err := NewCGRConfigFromJSONStringWithDefaults(cfgJSONStr); err != nil { t.Error(err) diff --git a/config/httpagntcfg_test.go b/config/httpagntcfg_test.go index 5693eb819..15c599f7d 100644 --- a/config/httpagntcfg_test.go +++ b/config/httpagntcfg_test.go @@ -533,14 +533,14 @@ func TestHttpAgentCfgAsMapInterface(t *testing.T) { }` eMap := []map[string]interface{}{ { - utils.IdCfg: "conecto1", + utils.IDCfg: "conecto1", utils.URLCfg: "/conecto", utils.SessionSConnsCfg: []string{"*localhost"}, utils.RequestPayloadCfg: "*url", utils.ReplyPayloadCfg: "*xml", utils.RequestProcessorsCfg: []map[string]interface{}{ { - utils.IdCfg: "OutboundAUTHDryRun", + utils.IDCfg: "OutboundAUTHDryRun", utils.FiltersCfg: []string{"*string:~*req.request_type:OutboundAUTH", "*string:~*req.Msisdn:497700056231"}, utils.TenantCfg: "cgrates.org", utils.FlagsCfg: []string{"*dryrun"}, diff --git a/config/libconfig_json.go b/config/libconfig_json.go index d856c25ed..b4f297d87 100755 --- a/config/libconfig_json.go +++ b/config/libconfig_json.go @@ -49,8 +49,6 @@ type GeneralJsonCfg struct { Digest_equal *string Rsr_separator *string Max_parallel_conns *int - Concurrent_requests *int - Concurrent_strategy *string } // Listen config section @@ -661,3 +659,9 @@ type APIBanJsonCfg struct { Enabled *bool Keys *[]string } + +type CoreSJsonCfg struct { + Caps *int + Caps_strategy *string + Caps_stats_interval *string +} diff --git a/config/loaderscfg.go b/config/loaderscfg.go index 7721183a1..6aab6c56e 100644 --- a/config/loaderscfg.go +++ b/config/loaderscfg.go @@ -211,7 +211,7 @@ func (lData *LoaderDataType) AsMapInterface(separator string) (initialMP map[str func (l *LoaderSCfg) AsMapInterface(separator string) (initialMP map[string]interface{}) { initialMP = map[string]interface{}{ - utils.IdCfg: l.Id, + utils.IDCfg: l.Id, utils.EnabledCfg: l.Enabled, utils.DryRunCfg: l.DryRun, utils.LockFileNameCfg: l.LockFileName, diff --git a/config/loaderscfg_test.go b/config/loaderscfg_test.go index d312bbc9a..cb9db28e4 100644 --- a/config/loaderscfg_test.go +++ b/config/loaderscfg_test.go @@ -271,7 +271,7 @@ func TestLoaderCfgAsMapInterfaceCase1(t *testing.T) { }` eMap := []map[string]interface{}{ { - utils.IdCfg: "*default", + utils.IDCfg: "*default", utils.EnabledCfg: false, utils.TenantCfg: "~*req.Destination1", utils.DryRunCfg: false, @@ -355,7 +355,7 @@ func TestLoaderCfgAsMapInterfaceCase2(t *testing.T) { }` eMap := []map[string]interface{}{ { - utils.IdCfg: "*default", + utils.IDCfg: "*default", utils.EnabledCfg: false, utils.TenantCfg: "~*req.Destination1", utils.DryRunCfg: false, diff --git a/config/multifiles_it_test.go b/config/multifiles_it_test.go index ecb30511d..d5878422a 100644 --- a/config/multifiles_it_test.go +++ b/config/multifiles_it_test.go @@ -53,31 +53,30 @@ func TestMfGeneralItems(t *testing.T) { func TestMfEnvReaderITRead(t *testing.T) { expected := GeneralCfg{ - NodeID: "d80fac5", - Logger: "*syslog", - LogLevel: 6, - RoundingDecimals: 5, - DBDataEncoding: "msgpack", - TpExportPath: "/var/spool/cgrates/tpe", - PosterAttempts: 3, - FailedPostsDir: "/var/spool/cgrates/failed_posts", - DefaultReqType: utils.META_PSEUDOPREPAID, - DefaultCategory: "call", - DefaultTenant: "cgrates.org", - DefaultCaching: utils.MetaReload, - DefaultTimezone: "Local", - ConnectAttempts: 3, - Reconnects: -1, - MaxCallDuration: 3 * time.Hour, - ConnectTimeout: time.Second, - ReplyTimeout: 2 * time.Second, - LockingTimeout: 0, - DigestSeparator: ",", - DigestEqual: ":", - RSRSep: ";", - MaxParallelConns: 100, - FailedPostsTTL: 5 * time.Second, - ConcurrentStrategy: utils.MetaBusy, + NodeID: "d80fac5", + Logger: "*syslog", + LogLevel: 6, + RoundingDecimals: 5, + DBDataEncoding: "msgpack", + TpExportPath: "/var/spool/cgrates/tpe", + PosterAttempts: 3, + FailedPostsDir: "/var/spool/cgrates/failed_posts", + DefaultReqType: utils.META_PSEUDOPREPAID, + DefaultCategory: "call", + DefaultTenant: "cgrates.org", + DefaultCaching: utils.MetaReload, + DefaultTimezone: "Local", + ConnectAttempts: 3, + Reconnects: -1, + MaxCallDuration: 3 * time.Hour, + ConnectTimeout: time.Second, + ReplyTimeout: 2 * time.Second, + LockingTimeout: 0, + DigestSeparator: ",", + DigestEqual: ":", + RSRSep: ";", + MaxParallelConns: 100, + FailedPostsTTL: 5 * time.Second, } if !reflect.DeepEqual(expected, *mfCgrCfg.generalCfg) { t.Errorf("Expected: %+v\n, received: %+v", utils.ToJSON(expected), utils.ToJSON(*mfCgrCfg.generalCfg)) diff --git a/config/radiuscfg_test.go b/config/radiuscfg_test.go index 2b93be563..49962b098 100644 --- a/config/radiuscfg_test.go +++ b/config/radiuscfg_test.go @@ -185,7 +185,7 @@ func TestRadiusAgentCfgAsMapInterface(t *testing.T) { utils.SessionSConnsCfg: []string{"*conn1", "*conn2"}, utils.RequestProcessorsCfg: []map[string]interface{}{ { - utils.IdCfg: "OutboundAUTHDryRun", + utils.IDCfg: "OutboundAUTHDryRun", utils.FiltersCfg: []string{"*string:~*req.request_type:OutboundAUTH", "*string:~*req.Msisdn:497700056231"}, utils.TenantCfg: "cgrates.org", utils.FlagsCfg: []string{"*dryrun"}, diff --git a/config/ralscfg.go b/config/ralscfg.go index 0380012fb..479844c78 100644 --- a/config/ralscfg.go +++ b/config/ralscfg.go @@ -118,7 +118,7 @@ func (ralsCfg *RalsCfg) AsMapInterface() (initialMP map[string]interface{}) { utils.RpSubjectPrefixMatchingCfg: ralsCfg.RpSubjectPrefixMatching, utils.RemoveExpiredCfg: ralsCfg.RemoveExpired, utils.MaxIncrementsCfg: ralsCfg.MaxIncrements, - utils.Dynaprepaid_actionplansCfg: ralsCfg.DynaprepaidActionPlans, + utils.DynaprepaidActionplansCfg: ralsCfg.DynaprepaidActionPlans, } if ralsCfg.ThresholdSConns != nil { threSholds := make([]string, len(ralsCfg.ThresholdSConns)) diff --git a/config/ralscfg_test.go b/config/ralscfg_test.go index ecd035af4..b7bef963d 100644 --- a/config/ralscfg_test.go +++ b/config/ralscfg_test.go @@ -124,7 +124,7 @@ func TestRalsCfgAsMapInterfaceCase1(t *testing.T) { "*any": "*zero1ns", "*voice": "*zero1s", }, - utils.Dynaprepaid_actionplansCfg: []string{}, + utils.DynaprepaidActionplansCfg: []string{}, } if cgrCfg, err := NewCGRConfigFromJSONStringWithDefaults(cfgJSONStr); err != nil { t.Error(err) @@ -159,7 +159,7 @@ func TestRalsCfgAsMapInterfaceCase2(t *testing.T) { "*any": "*zero1ns", "*voice": "*zero1s", }, - utils.Dynaprepaid_actionplansCfg: []string{}, + utils.DynaprepaidActionplansCfg: []string{}, } if cgrCfg, err := NewCGRConfigFromJSONStringWithDefaults(cfgJSONStr); err != nil { t.Error(err) diff --git a/config/sipagentcfg_test.go b/config/sipagentcfg_test.go index 4b7573db0..cc8c8b6b7 100644 --- a/config/sipagentcfg_test.go +++ b/config/sipagentcfg_test.go @@ -260,7 +260,7 @@ func TestSIPAgentCfgAsMapInterface1(t *testing.T) { utils.RetransmissionTimerCfg: 5 * time.Second, utils.RequestProcessorsCfg: []map[string]interface{}{ { - utils.IdCfg: "OutboundAUTHDryRun", + utils.IDCfg: "OutboundAUTHDryRun", utils.FiltersCfg: []string{"*string:~*req.request_type:OutboundAUTH", "*string:~*req.Msisdn:497700056231"}, utils.TenantCfg: "cgrates.org", utils.FlagsCfg: []string{"*dryrun"}, @@ -314,7 +314,7 @@ func TestSIPAgentCfgAsMapInterface2(t *testing.T) { utils.RetransmissionTimerCfg: time.Second, utils.RequestProcessorsCfg: []map[string]interface{}{ { - utils.IdCfg: "Register", + utils.IDCfg: "Register", utils.FiltersCfg: []string{"*notstring:~*vars.Method:INVITE"}, utils.TenantCfg: "cgrates.org", utils.FlagsCfg: []string{"*none"}, diff --git a/console/sleep.go b/console/sleep.go index 69e182560..965b5b629 100644 --- a/console/sleep.go +++ b/console/sleep.go @@ -54,7 +54,7 @@ func (cmd *CmdSleep) RpcParams(reset bool) interface{} { func (cmd *CmdSleep) PostprocessRpcParams() (err error) { params := new(utils.DurationArgs) if val, can := cmd.rpcParams.(*StringWrapper); can { - params.DurationTime, err = utils.ParseDurationWithNanosecs(val.Item) + params.Duration, err = utils.ParseDurationWithNanosecs(val.Item) if err != nil { return } diff --git a/utils/basic_auth.go b/cores/basic_auth.go similarity index 87% rename from utils/basic_auth.go rename to cores/basic_auth.go index d1bc0bcbe..6b47f02af 100644 --- a/utils/basic_auth.go +++ b/cores/basic_auth.go @@ -16,13 +16,15 @@ You should have received a copy of the GNU General Public License along with this program. If not, see */ -package utils +package cores import ( "encoding/base64" "fmt" "net/http" "strings" + + "github.com/cgrates/cgrates/utils" ) // use provides a cleaner interface for chaining middleware for single routes. @@ -52,28 +54,28 @@ func basicAuth(userList map[string]string) basicAuthMiddleware { authHeader := strings.SplitN(r.Header.Get("Authorization"), " ", 2) if len(authHeader) != 2 { - Logger.Warning(" Missing authorization header value") + utils.Logger.Warning(" Missing authorization header value") http.Error(w, "Not authorized", 401) return } authHeaderDecoded, err := base64.StdEncoding.DecodeString(authHeader[1]) if err != nil { - Logger.Warning(" Unable to decode authorization header") + utils.Logger.Warning(" Unable to decode authorization header") http.Error(w, err.Error(), 401) return } userPass := strings.SplitN(string(authHeaderDecoded), ":", 2) if len(userPass) != 2 { - Logger.Warning(" Unauthorized API access. Missing or extra credential components") + utils.Logger.Warning(" Unauthorized API access. Missing or extra credential components") http.Error(w, "Not authorized", 401) return } valid := verifyCredential(userPass[0], userPass[1], userList) if !valid { - Logger.Warning(fmt.Sprintf(" Unauthorized API access by user '%s'", userPass[0])) + utils.Logger.Warning(fmt.Sprintf(" Unauthorized API access by user '%s'", userPass[0])) http.Error(w, "Not authorized", 401) return } diff --git a/utils/basic_auth_test.go b/cores/basic_auth_test.go similarity index 99% rename from utils/basic_auth_test.go rename to cores/basic_auth_test.go index b2caa9c66..415e90302 100644 --- a/utils/basic_auth_test.go +++ b/cores/basic_auth_test.go @@ -15,7 +15,7 @@ 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 utils +package cores import ( "encoding/base64" diff --git a/cores/caps.go b/cores/caps.go new file mode 100644 index 000000000..fed93551c --- /dev/null +++ b/cores/caps.go @@ -0,0 +1,224 @@ +/* +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 cores + +import ( + "net" + "net/rpc" + "net/rpc/jsonrpc" + "strconv" + "sync" + "time" + + "github.com/cgrates/cgrates/analyzers" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +// Caps the structure that allocs requests for API +type Caps struct { + strategy string + aReqs chan struct{} +} + +// NewCaps creates a new caps +func NewCaps(reqs int, strategy string) *Caps { + cR := &Caps{ + strategy: strategy, + aReqs: make(chan struct{}, reqs), + } + return cR +} + +// IsLimited returns true if the limit is not 0 +func (cR *Caps) IsLimited() bool { + return cap(cR.aReqs) != 0 +} + +// Allocated returns the number of requests actively serviced +func (cR *Caps) Allocated() int { + return len(cR.aReqs) +} + +// Allocate will reserve a channel for the API call +func (cR *Caps) Allocate() (err error) { + switch cR.strategy { + case utils.MetaBusy: + if len(cR.aReqs) == cap(cR.aReqs) { + return utils.ErrMaxConcurentRPCExceededNoCaps + } + fallthrough + case utils.MetaQueue: + cR.aReqs <- struct{}{} + } + return +} + +// Deallocate will free a channel for the API call +func (cR *Caps) Deallocate() { + <-cR.aReqs + return +} + +type conn interface { + Read(b []byte) (n int, err error) + Write(b []byte) (n int, err error) + Close() error + LocalAddr() net.Addr + RemoteAddr() net.Addr +} + +func newCapsGOBCodec(conn conn, caps *Caps, anz *analyzers.AnalyzerService) (r rpc.ServerCodec) { + r = newCapsServerCodec(newGobServerCodec(conn), caps) + if anz != nil { + from := conn.RemoteAddr() + var fromstr string + if from != nil { + fromstr = from.String() + } + to := conn.LocalAddr() + var tostr string + if to != nil { + tostr = to.String() + } + return analyzers.NewServerCodec(r, anz, utils.MetaGOB, fromstr, tostr) + } + return +} + +func newCapsJSONCodec(conn conn, caps *Caps, anz *analyzers.AnalyzerService) (r rpc.ServerCodec) { + r = newCapsServerCodec(jsonrpc.NewServerCodec(conn), caps) + if anz != nil { + from := conn.RemoteAddr() + var fromstr string + if from != nil { + fromstr = from.String() + } + to := conn.LocalAddr() + var tostr string + if to != nil { + tostr = to.String() + } + return analyzers.NewServerCodec(r, anz, utils.MetaJSON, fromstr, tostr) + } + return +} + +func newCapsServerCodec(sc rpc.ServerCodec, caps *Caps) rpc.ServerCodec { + if !caps.IsLimited() { + return sc + } + return &capsServerCodec{ + sc: sc, + caps: caps, + } +} + +type capsServerCodec struct { + sc rpc.ServerCodec + caps *Caps +} + +func (c *capsServerCodec) ReadRequestHeader(r *rpc.Request) error { + return c.sc.ReadRequestHeader(r) +} + +func (c *capsServerCodec) ReadRequestBody(x interface{}) error { + if err := c.caps.Allocate(); err != nil { + return err + } + return c.sc.ReadRequestBody(x) +} +func (c *capsServerCodec) WriteResponse(r *rpc.Response, x interface{}) error { + if r.Error == utils.ErrMaxConcurentRPCExceededNoCaps.Error() { + r.Error = utils.ErrMaxConcurentRPCExceeded.Error() + } else { + defer c.caps.Deallocate() + } + return c.sc.WriteResponse(r, x) +} +func (c *capsServerCodec) Close() error { return c.sc.Close() } + +// NewCapsStats returns the stats for the caps +func NewCapsStats(sampleinterval time.Duration, caps *Caps, exitChan chan bool) (cs *CapsStats) { + st, _ := engine.NewStatAverage(1, utils.MetaDynReq, nil) + cs = &CapsStats{st: st} + go cs.loop(sampleinterval, exitChan, caps) + return +} + +// CapsStats stores the stats for caps +type CapsStats struct { + sync.RWMutex + st engine.StatMetric + peak int +} + +// OnEvict the function that should be called on cache eviction +func (cs *CapsStats) OnEvict(itmID string, value interface{}) { + cs.st.RemEvent(itmID) +} + +func (cs *CapsStats) loop(intr time.Duration, exitChan chan bool, caps *Caps) { + for { + select { + case v := <-exitChan: + exitChan <- v + return + case <-time.After(intr): + evID := time.Now().String() + val := caps.Allocated() + cs.addSample(evID, val) + } + } +} + +func (cs *CapsStats) addSample(evID string, val int) { + cs.Lock() + engine.Cache.SetWithoutReplicate(utils.CacheCapsEvents, evID, val, nil, true, utils.NonTransactional) + cs.st.AddEvent(evID, floatDP(val)) + if val > cs.peak { + cs.peak = val + } + cs.Unlock() +} + +// GetPeak returns the maximum allocated caps +func (cs *CapsStats) GetPeak() (peak int) { + cs.RLock() + peak = cs.peak + cs.RUnlock() + return +} + +// GetAverage returns the average allocated caps +func (cs *CapsStats) GetAverage(roundingDecimals int) (avg float64) { + cs.RLock() + avg = cs.st.GetFloat64Value(roundingDecimals) + cs.RUnlock() + return +} + +// floatDP should be only used by capstats +type floatDP float64 + +func (f floatDP) String() string { return strconv.FormatFloat(float64(f), 'f', -1, 64) } +func (f floatDP) FieldAsInterface(fldPath []string) (interface{}, error) { return float64(f), nil } +func (f floatDP) FieldAsString(fldPath []string) (string, error) { return f.String(), nil } +func (f floatDP) RemoteHost() net.Addr { return nil } diff --git a/cores/caps_test.go b/cores/caps_test.go new file mode 100644 index 000000000..a0d5d66ad --- /dev/null +++ b/cores/caps_test.go @@ -0,0 +1,253 @@ +/* +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 cores + +import ( + "net" + "net/rpc" + "net/rpc/jsonrpc" + "reflect" + "testing" + "time" + + "github.com/cgrates/cgrates/analyzers" + "github.com/cgrates/cgrates/engine" + "github.com/cgrates/cgrates/utils" +) + +func TestNewCaps(t *testing.T) { + exp := &Caps{ + strategy: utils.MetaBusy, + aReqs: make(chan struct{}, 0), + } + cs := NewCaps(0, utils.MetaBusy) + + // only check the strategy + if !reflect.DeepEqual(exp.strategy, cs.strategy) { + t.Errorf("Expected: %v ,received: %v", exp, cs) + } + + if cs.IsLimited() { + t.Errorf("Expected to not be limited") + } + + if al := cs.Allocated(); al != 0 { + t.Errorf("Expected: %v ,received: %v", 0, al) + } + if err := cs.Allocate(); err != utils.ErrMaxConcurentRPCExceededNoCaps { + t.Errorf("Expected: %v ,received: %v", utils.ErrMaxConcurentRPCExceededNoCaps, err) + } + cs = NewCaps(1, utils.MetaBusy) + if err := cs.Allocate(); err != nil { + t.Error(err) + } + cs.Deallocate() +} + +func TestCapsStats(t *testing.T) { + st, err := engine.NewStatAverage(1, utils.MetaDynReq, nil) + if err != nil { + t.Error(err) + } + exp := &CapsStats{st: st} + cr := NewCaps(0, utils.MetaBusy) + exitChan := make(chan bool, 1) + exitChan <- true + cs := NewCapsStats(1, cr, exitChan) + if !reflect.DeepEqual(exp, cs) { + t.Errorf("Expected: %v ,received: %v", exp, cs) + } + <-exitChan + go func() { + time.Sleep(100) + exitChan <- true + }() + cr = NewCaps(10, utils.MetaBusy) + cr.Allocate() + cr.Allocate() + cs.loop(1, exitChan, cr) + if avg := cs.GetAverage(2); avg <= 0 { + t.Errorf("Expected at least an event to be processed: %v", avg) + } + if pk := cs.GetPeak(); pk != 2 { + t.Errorf("Expected the peak to be 2 received: %v", pk) + } +} + +func TestCapsStatsGetAverage(t *testing.T) { + st, err := engine.NewStatAverage(1, utils.MetaDynReq, nil) + if err != nil { + t.Error(err) + } + cs := &CapsStats{st: st} + cs.addSample("1", 10) + expAvg := 10. + if avg := cs.GetAverage(2); avg != expAvg { + t.Errorf("Expected: %v ,received: %v", expAvg, avg) + } + expPk := 10 + if pk := cs.GetPeak(); pk != expPk { + t.Errorf("Expected: %v ,received:%v", expPk, pk) + } + cs.addSample("2", 16) + expAvg = 13. + if avg := cs.GetAverage(2); avg != expAvg { + t.Errorf("Expected: %v ,received: %v", expAvg, avg) + } + expPk = 16 + if pk := cs.GetPeak(); pk != expPk { + t.Errorf("Expected: %v ,received:%v", expPk, pk) + } + cs.OnEvict("2", nil) + expAvg = 10. + if avg := cs.GetAverage(2); avg != expAvg { + t.Errorf("Expected: %v ,received: %v", expAvg, avg) + } + if pk := cs.GetPeak(); pk != expPk { + t.Errorf("Expected: %v ,received:%v", expPk, pk) + } +} + +func TestFloatDP(t *testing.T) { + f := floatDP(10.) + expStr := "10" + if s := f.String(); s != expStr { + t.Errorf("Expected: %v ,received:%v", expStr, s) + } + if s, err := f.FieldAsString(nil); err != nil { + t.Error(err) + } else if s != expStr { + t.Errorf("Expected: %v ,received:%v", expStr, s) + } + if r := f.RemoteHost(); r != nil { + t.Errorf("Expected remote host to be nil received:%v", r) + } + exp := 10. + if s, err := f.FieldAsInterface(nil); err != nil { + t.Error(err) + } else if s != exp { + t.Errorf("Expected: %v ,received:%v", exp, s) + } +} + +type mockServerCodec struct{} + +func (c *mockServerCodec) ReadRequestHeader(r *rpc.Request) (err error) { + r.Seq = 0 + r.ServiceMethod = utils.CoreSv1Ping + return +} + +func (c *mockServerCodec) ReadRequestBody(x interface{}) (err error) { + return +} +func (c *mockServerCodec) WriteResponse(r *rpc.Response, x interface{}) error { + return nil +} +func (c *mockServerCodec) Close() error { return nil } + +func TestNewCapsServerCodec(t *testing.T) { + mk := new(mockServerCodec) + cr := NewCaps(0, utils.MetaBusy) + if r := newCapsServerCodec(mk, cr); !reflect.DeepEqual(mk, r) { + t.Errorf("Expected: %v ,received:%v", mk, r) + } + cr = NewCaps(1, utils.MetaBusy) + exp := &capsServerCodec{ + sc: mk, + caps: cr, + } + codec := newCapsServerCodec(mk, cr) + if !reflect.DeepEqual(exp, codec) { + t.Errorf("Expected: %v ,received:%v", exp, codec) + } + var err error + r := new(rpc.Request) + expR := &rpc.Request{ + Seq: 0, + ServiceMethod: utils.CoreSv1Ping, + } + if err = codec.ReadRequestHeader(r); err != nil { + t.Fatal(err) + } else if !reflect.DeepEqual(r, expR) { + t.Errorf("Expected: %v ,received:%v", expR, r) + } + + if err = codec.ReadRequestBody("args"); err != nil { + t.Fatal(err) + } + + if err = codec.ReadRequestBody("args"); err != utils.ErrMaxConcurentRPCExceededNoCaps { + t.Errorf("Expected error: %v ,received: %v ", utils.ErrMaxConcurentRPCExceededNoCaps, err) + } + + if err = codec.WriteResponse(&rpc.Response{ + Error: "error", + Seq: 0, + ServiceMethod: utils.CoreSv1Ping, + }, "reply"); err != nil { + t.Fatal(err) + } + + if err = codec.WriteResponse(&rpc.Response{ + Error: utils.ErrMaxConcurentRPCExceededNoCaps.Error(), + Seq: 0, + ServiceMethod: utils.CoreSv1Ping, + }, "reply"); err != nil { + t.Fatal(err) + } + if err = codec.Close(); err != nil { + t.Fatal(err) + } +} + +type mockConn struct{} + +func (*mockConn) Read(b []byte) (n int, err error) { return } +func (*mockConn) Write(b []byte) (n int, err error) { return } +func (*mockConn) Close() error { return nil } +func (*mockConn) LocalAddr() net.Addr { return utils.LocalAddr() } +func (*mockConn) RemoteAddr() net.Addr { return utils.LocalAddr() } + +func TestNewCapsGOBCodec(t *testing.T) { + conn := new(mockConn) + cr := NewCaps(0, utils.MetaBusy) + anz := &analyzers.AnalyzerService{} + exp := newGobServerCodec(conn) + if r := newCapsGOBCodec(conn, cr, nil); !reflect.DeepEqual(r, exp) { + t.Errorf("Expected: %v ,received:%v", exp, r) + } + exp = analyzers.NewServerCodec(newGobServerCodec(conn), anz, utils.MetaGOB, utils.Local, utils.Local) + if r := newCapsGOBCodec(conn, cr, anz); !reflect.DeepEqual(r, exp) { + t.Errorf("Expected: %v ,received:%v", exp, r) + } +} + +func TestNewCapsJSONCodec(t *testing.T) { + conn := new(mockConn) + cr := NewCaps(0, utils.MetaBusy) + anz := &analyzers.AnalyzerService{} + exp := jsonrpc.NewServerCodec(conn) + if r := newCapsJSONCodec(conn, cr, nil); !reflect.DeepEqual(r, exp) { + t.Errorf("Expected: %v ,received:%v", exp, r) + } + exp = analyzers.NewServerCodec(jsonrpc.NewServerCodec(conn), anz, utils.MetaJSON, utils.Local, utils.Local) + if r := newCapsJSONCodec(conn, cr, anz); !reflect.DeepEqual(r, exp) { + t.Errorf("Expected: %v ,received:%v", exp, r) + } +} diff --git a/engine/core.go b/cores/core.go similarity index 81% rename from engine/core.go rename to cores/core.go index df15ebcd7..1df533503 100644 --- a/engine/core.go +++ b/cores/core.go @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see */ -package engine +package cores import ( "fmt" @@ -26,11 +26,21 @@ import ( "github.com/cgrates/cgrates/utils" ) -func NewCoreService() *CoreService { - return &CoreService{} +func NewCoreService(cfg *config.CGRConfig, caps *Caps, exitChan chan bool) *CoreService { + var st *CapsStats + if caps.IsLimited() && cfg.CoreSCfg().CapsStatsInterval != 0 { + st = NewCapsStats(cfg.CoreSCfg().CapsStatsInterval, caps, exitChan) + } + return &CoreService{ + cfg: cfg, + capsStats: st, + } } -type CoreService struct{} +type CoreService struct { + cfg *config.CGRConfig + capsStats *CapsStats +} // ListenAndServe will initialize the service func (cS *CoreService) ListenAndServe(exitChan chan bool) (err error) { @@ -51,7 +61,7 @@ func (cS *CoreService) Status(arg *utils.TenantWithOpts, reply *map[string]inter memstats := new(runtime.MemStats) runtime.ReadMemStats(memstats) response := make(map[string]interface{}) - response[utils.NodeID] = config.CgrConfig().GeneralCfg().NodeID + response[utils.NodeID] = cS.cfg.GeneralCfg().NodeID response[utils.MemoryUsage] = utils.SizeFmt(float64(memstats.HeapAlloc), "") response[utils.ActiveGoroutines] = runtime.NumGoroutine() if response[utils.Version], err = utils.GetCGRVersion(); err != nil { diff --git a/utils/gob_codec.go b/cores/gob_codec.go similarity index 99% rename from utils/gob_codec.go rename to cores/gob_codec.go index 087b57b3c..65f228e14 100644 --- a/utils/gob_codec.go +++ b/cores/gob_codec.go @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see */ -package utils +package cores import ( "bufio" diff --git a/utils/server.go b/cores/server.go similarity index 80% rename from utils/server.go rename to cores/server.go index 6a7eceb26..bce8b9742 100644 --- a/utils/server.go +++ b/cores/server.go @@ -16,7 +16,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see */ -package utils +package cores import ( "bytes" @@ -38,6 +38,8 @@ import ( "time" rpc2_jsonrpc "github.com/cenkalti/rpc2/jsonrpc" + "github.com/cgrates/cgrates/analyzers" + "github.com/cgrates/cgrates/utils" "github.com/cenkalti/rpc2" "golang.org/x/net/websocket" @@ -51,17 +53,12 @@ func init() { gob.Register(url.Values{}) } -type anzWrapFunc func(conn rpc.ServerCodec, enc string, from, to net.Addr) rpc.ServerCodec - -func NewServer(concReqs *ConcReqs) (s *Server) { +func NewServer(caps *Caps) (s *Server) { return &Server{ httpMux: http.NewServeMux(), httpsMux: http.NewServeMux(), stopbiRPCServer: make(chan struct{}, 1), - concReqs: concReqs, - anzWrapper: func(conn rpc.ServerCodec, enc string, from, to net.Addr) rpc.ServerCodec { - return conn - }, + caps: caps, } } @@ -73,16 +70,16 @@ type Server struct { stopbiRPCServer chan struct{} // used in order to fully stop the biRPC httpsMux *http.ServeMux httpMux *http.ServeMux - anzWrapper anzWrapFunc - concReqs *ConcReqs + caps *Caps + anz *analyzers.AnalyzerService } -func (s *Server) SetAnzWrapperFunc(anz anzWrapFunc) { - s.anzWrapper = anz +func (s *Server) SetAnalyzer(anz *analyzers.AnalyzerService) { + s.anz = anz } func (s *Server) RpcRegister(rcvr interface{}) { - RegisterRpcParams(EmptyString, rcvr) + utils.RegisterRpcParams(utils.EmptyString, rcvr) rpc.Register(rcvr) s.Lock() s.rpcEnabled = true @@ -90,7 +87,7 @@ func (s *Server) RpcRegister(rcvr interface{}) { } func (s *Server) RpcRegisterName(name string, rcvr interface{}) { - RegisterRpcParams(name, rcvr) + utils.RegisterRpcParams(name, rcvr) rpc.RegisterName(name, rcvr) s.Lock() s.rpcEnabled = true @@ -160,19 +157,19 @@ func (s *Server) ServeJSON(addr string, exitChan chan bool) { return } - lJSON, e := net.Listen(TCP, addr) + lJSON, e := net.Listen(utils.TCP, addr) if e != nil { log.Println("ServeJSON listen error:", e) exitChan <- true return } - Logger.Info(fmt.Sprintf("Starting CGRateS JSON server at <%s>.", addr)) + utils.Logger.Info(fmt.Sprintf("Starting CGRateS JSON server at <%s>.", addr)) errCnt := 0 var lastErrorTime time.Time for { conn, err := lJSON.Accept() if err != nil { - Logger.Err(fmt.Sprintf(" JSON accept error: <%s>", err.Error())) + utils.Logger.Err(fmt.Sprintf(" JSON accept error: <%s>", err.Error())) now := time.Now() if now.Sub(lastErrorTime) > 5*time.Second { errCnt = 0 // reset error count if last error was more than 5 seconds ago @@ -184,7 +181,7 @@ func (s *Server) ServeJSON(addr string, exitChan chan bool) { } continue } - go rpc.ServeCodec(newConcReqsJSONCodec(conn, s.concReqs, s.anzWrapper)) + go rpc.ServeCodec(newCapsJSONCodec(conn, s.caps, s.anz)) } } @@ -196,19 +193,19 @@ func (s *Server) ServeGOB(addr string, exitChan chan bool) { if !enabled { return } - lGOB, e := net.Listen(TCP, addr) + lGOB, e := net.Listen(utils.TCP, addr) if e != nil { log.Println("ServeGOB listen error:", e) exitChan <- true return } - Logger.Info(fmt.Sprintf("Starting CGRateS GOB server at <%s>.", addr)) + utils.Logger.Info(fmt.Sprintf("Starting CGRateS GOB server at <%s>.", addr)) errCnt := 0 var lastErrorTime time.Time for { conn, err := lGOB.Accept() if err != nil { - Logger.Err(fmt.Sprintf(" GOB accept error: <%s>", err.Error())) + utils.Logger.Err(fmt.Sprintf(" GOB accept error: <%s>", err.Error())) now := time.Now() if now.Sub(lastErrorTime) > 5*time.Second { errCnt = 0 // reset error count if last error was more than 5 seconds ago @@ -220,16 +217,16 @@ func (s *Server) ServeGOB(addr string, exitChan chan bool) { } continue } - go rpc.ServeCodec(newConcReqsGOBCodec(conn, s.concReqs, s.anzWrapper)) + go rpc.ServeCodec(newCapsGOBCodec(conn, s.caps, s.anz)) } } func (s *Server) handleRequest(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() w.Header().Set("Content-Type", "application/json") - rmtIP, _ := GetRemoteIP(r) - rmtAddr, _ := net.ResolveIPAddr(EmptyString, rmtIP) - res := newRPCRequest(r.Body, rmtAddr, s.concReqs, s.anzWrapper).Call() + rmtIP, _ := utils.GetRemoteIP(r) + rmtAddr, _ := net.ResolveIPAddr(utils.EmptyString, rmtIP) + res := newRPCRequest(r.Body, rmtAddr, s.caps, s.anz).Call() io.Copy(w, res) } @@ -269,7 +266,7 @@ func (s *Server) ServeHTTP(addr string, jsonRPCURL string, wsRPCURL string, s.httpEnabled = true s.Unlock() - Logger.Info(" enabling handler for JSON-RPC") + utils.Logger.Info(" enabling handler for JSON-RPC") if useBasicAuth { s.httpMux.HandleFunc(jsonRPCURL, use(s.handleRequest, basicAuth(userList))) } else { @@ -280,9 +277,9 @@ func (s *Server) ServeHTTP(addr string, jsonRPCURL string, wsRPCURL string, s.Lock() s.httpEnabled = true s.Unlock() - Logger.Info(" enabling handler for WebSocket connections") + utils.Logger.Info(" enabling handler for WebSocket connections") wsHandler := websocket.Handler(func(ws *websocket.Conn) { - rpc.ServeCodec(newConcReqsJSONCodec(ws, s.concReqs, s.anzWrapper)) + rpc.ServeCodec(newCapsJSONCodec(ws, s.caps, s.anz)) }) if useBasicAuth { s.httpMux.HandleFunc(wsRPCURL, use(func(w http.ResponseWriter, r *http.Request) { @@ -296,9 +293,9 @@ func (s *Server) ServeHTTP(addr string, jsonRPCURL string, wsRPCURL string, return } if useBasicAuth { - Logger.Info(" enabling basic auth") + utils.Logger.Info(" enabling basic auth") } - Logger.Info(fmt.Sprintf(" start listening at <%s>", addr)) + utils.Logger.Info(fmt.Sprintf(" start listening at <%s>", addr)) if err := http.ListenAndServe(addr, s.httpMux); err != nil { log.Println(fmt.Sprintf("Error: %s when listening ", err)) } @@ -314,14 +311,14 @@ func (s *Server) ServeBiJSON(addr string, onConn func(*rpc2.Client), onDis func( return fmt.Errorf("BiRPCServer should not be nil") } var lBiJSON net.Listener - lBiJSON, err = net.Listen(TCP, addr) + lBiJSON, err = net.Listen(utils.TCP, addr) if err != nil { log.Println("ServeBiJSON listen error:", err) return } s.birpcSrv.OnConnect(onConn) s.birpcSrv.OnDisconnect(onDis) - Logger.Info(fmt.Sprintf("Starting CGRateS BiJSON server at <%s>", addr)) + utils.Logger.Info(fmt.Sprintf("Starting CGRateS BiJSON server at <%s>", addr)) go func(l net.Listener) { for { conn, err := l.Accept() @@ -353,12 +350,12 @@ type rpcRequest struct { rw io.ReadWriter // holds the JSON formated RPC response done chan bool // signals then end of the RPC request remoteAddr net.Addr - concReqs *ConcReqs - anzWarpper anzWrapFunc + caps *Caps + anzWarpper *analyzers.AnalyzerService } // newRPCRequest returns a new rpcRequest. -func newRPCRequest(r io.Reader, remoteAddr net.Addr, concReqs *ConcReqs, anz anzWrapFunc) *rpcRequest { +func newRPCRequest(r io.Reader, remoteAddr net.Addr, caps *Caps, anz *analyzers.AnalyzerService) *rpcRequest { var buf bytes.Buffer done := make(chan bool) return &rpcRequest{ @@ -366,7 +363,7 @@ func newRPCRequest(r io.Reader, remoteAddr net.Addr, concReqs *ConcReqs, anz anz rw: &buf, done: done, remoteAddr: remoteAddr, - concReqs: concReqs, + caps: caps, anzWarpper: anz, } } @@ -382,7 +379,7 @@ func (r *rpcRequest) Write(p []byte) (n int, err error) { } func (r *rpcRequest) LocalAddr() net.Addr { - return LocalAddr() + return utils.LocalAddr() } func (r *rpcRequest) RemoteAddr() net.Addr { return r.remoteAddr @@ -395,7 +392,7 @@ func (r *rpcRequest) Close() error { // Call invokes the RPC request, waits for it to complete, and returns the results. func (r *rpcRequest) Call() io.Reader { - go rpc.ServeCodec(newConcReqsJSONCodec(r, r.concReqs, r.anzWarpper)) + go rpc.ServeCodec(newCapsJSONCodec(r, r.caps, r.anzWarpper)) <-r.done return r.rw } @@ -451,21 +448,21 @@ func (s *Server) ServeGOBTLS(addr, serverCrt, serverKey, caCert string, if err != nil { return } - listener, err := tls.Listen(TCP, addr, config) + listener, err := tls.Listen(utils.TCP, addr, config) if err != nil { log.Println(fmt.Sprintf("Error: %s when listening", err)) exitChan <- true return } - Logger.Info(fmt.Sprintf("Starting CGRateS GOB TLS server at <%s>.", addr)) + utils.Logger.Info(fmt.Sprintf("Starting CGRateS GOB TLS server at <%s>.", addr)) errCnt := 0 var lastErrorTime time.Time for { conn, err := listener.Accept() defer conn.Close() if err != nil { - Logger.Err(fmt.Sprintf(" TLS accept error: <%s>", err.Error())) + utils.Logger.Err(fmt.Sprintf(" TLS accept error: <%s>", err.Error())) now := time.Now() if now.Sub(lastErrorTime) > 5*time.Second { errCnt = 0 // reset error count if last error was more than 5 seconds ago @@ -477,7 +474,7 @@ func (s *Server) ServeGOBTLS(addr, serverCrt, serverKey, caCert string, } continue } - go rpc.ServeCodec(newConcReqsGOBCodec(conn, s.concReqs, s.anzWrapper)) + go rpc.ServeCodec(newCapsGOBCodec(conn, s.caps, s.anz)) } } @@ -493,20 +490,20 @@ func (s *Server) ServeJSONTLS(addr, serverCrt, serverKey, caCert string, if err != nil { return } - listener, err := tls.Listen(TCP, addr, config) + listener, err := tls.Listen(utils.TCP, addr, config) if err != nil { log.Println(fmt.Sprintf("Error: %s when listening", err)) exitChan <- true return } - Logger.Info(fmt.Sprintf("Starting CGRateS JSON TLS server at <%s>.", addr)) + utils.Logger.Info(fmt.Sprintf("Starting CGRateS JSON TLS server at <%s>.", addr)) errCnt := 0 var lastErrorTime time.Time for { conn, err := listener.Accept() defer conn.Close() if err != nil { - Logger.Err(fmt.Sprintf(" TLS accept error: <%s>", err.Error())) + utils.Logger.Err(fmt.Sprintf(" TLS accept error: <%s>", err.Error())) now := time.Now() if now.Sub(lastErrorTime) > 5*time.Second { errCnt = 0 // reset error count if last error was more than 5 seconds ago @@ -518,7 +515,7 @@ func (s *Server) ServeJSONTLS(addr, serverCrt, serverKey, caCert string, } continue } - go rpc.ServeCodec(newConcReqsJSONCodec(conn, s.concReqs, s.anzWrapper)) + go rpc.ServeCodec(newCapsJSONCodec(conn, s.caps, s.anz)) } } @@ -536,7 +533,7 @@ func (s *Server) ServeHTTPTLS(addr, serverCrt, serverKey, caCert string, serverP s.Lock() s.httpEnabled = true s.Unlock() - Logger.Info(" enabling handler for JSON-RPC") + utils.Logger.Info(" enabling handler for JSON-RPC") if useBasicAuth { s.httpsMux.HandleFunc(jsonRPCURL, use(s.handleRequest, basicAuth(userList))) } else { @@ -547,9 +544,9 @@ func (s *Server) ServeHTTPTLS(addr, serverCrt, serverKey, caCert string, serverP s.Lock() s.httpEnabled = true s.Unlock() - Logger.Info(" enabling handler for WebSocket connections") + utils.Logger.Info(" enabling handler for WebSocket connections") wsHandler := websocket.Handler(func(ws *websocket.Conn) { - rpc.ServeCodec(newConcReqsJSONCodec(ws, s.concReqs, s.anzWrapper)) + rpc.ServeCodec(newCapsJSONCodec(ws, s.caps, s.anz)) }) if useBasicAuth { s.httpsMux.HandleFunc(wsRPCURL, use(func(w http.ResponseWriter, r *http.Request) { @@ -563,7 +560,7 @@ func (s *Server) ServeHTTPTLS(addr, serverCrt, serverKey, caCert string, serverP return } if useBasicAuth { - Logger.Info(" enabling basic auth") + utils.Logger.Info(" enabling basic auth") } config, err := loadTLSConfig(serverCrt, serverKey, caCert, serverPolicy, serverName) if err != nil { @@ -574,32 +571,10 @@ func (s *Server) ServeHTTPTLS(addr, serverCrt, serverKey, caCert string, serverP Handler: s.httpsMux, TLSConfig: config, } - Logger.Info(fmt.Sprintf(" start listening at <%s>", addr)) + utils.Logger.Info(fmt.Sprintf(" start listening at <%s>", addr)) if err := httpSrv.ListenAndServeTLS(serverCrt, serverKey); err != nil { log.Println(fmt.Sprintf("Error: %s when listening ", err)) } exitChan <- true return } - -// GetRemoteIP returns the IP from http request -func GetRemoteIP(r *http.Request) (ip string, err error) { - ip = r.Header.Get("X-REAL-IP") - if net.ParseIP(ip) != nil { - return - } - for _, ip = range strings.Split(r.Header.Get("X-FORWARDED-FOR"), FIELDS_SEP) { - if net.ParseIP(ip) != nil { - return - } - } - if ip, _, err = net.SplitHostPort(r.RemoteAddr); err != nil { - return - } - if net.ParseIP(ip) != nil { - return - } - ip = EmptyString - err = fmt.Errorf("no valid ip found") - return -} diff --git a/data/conf/cgrates/cgrates.json b/data/conf/cgrates/cgrates.json index 2a6d279e3..3f36bdf4a 100755 --- a/data/conf/cgrates/cgrates.json +++ b/data/conf/cgrates/cgrates.json @@ -32,8 +32,13 @@ // "digest_equal": ":", // equal symbol used in case of digests // "rsr_separator": ";", // separator used within RSR fields // "max_parallel_conns": 100, // the maximum number of connection used by the *parallel strategy -// "concurrent_requests": 0, // maximum concurrent request allowed ( 0 to disabled ) -// "concurrent_strategy": "*busy", // strategy in case in case of concurrent requests reached +// }, + + +// "cores": { +// "caps": 0, // maximum concurrent request allowed ( 0 to disabled ) +// "caps_strategy": "*busy", // strategy in case in case of concurrent requests reached +// "caps_stats_interval": "0" // the interval we sample for caps stats ( 0 to disabled ) // }, @@ -246,6 +251,7 @@ // "*uch": {"limit": -1, "ttl": "3h", "static_ttl": false, "replicate": false}, // User cache // "*stir": {"limit": -1, "ttl": "3h", "static_ttl": false, "replicate": false}, // stirShaken cache keys // "*apiban":{"limit": -1, "ttl": "2m", "static_ttl": false, "replicate": false}, +// "*caps_events": {"limit": -1, "ttl": "", "static_ttl": false, "replicate": false}, // caps cached samples // // only for *internal database // "*versions": {"limit": -1, "ttl": "", "static_ttl": false, "replicate": false}, // for version storing diff --git a/data/conf/samples/conc_reqs_busy/cgrates.json b/data/conf/samples/conc_reqs_busy/cgrates.json index d10fb36cc..46d138da0 100644 --- a/data/conf/samples/conc_reqs_busy/cgrates.json +++ b/data/conf/samples/conc_reqs_busy/cgrates.json @@ -4,8 +4,12 @@ "log_level": 7, "node_id": "ConcurrentBusyEngine", "reply_timeout": "50s", - "concurrent_requests": 2, - "concurrent_strategy": "*busy" +}, + + +"cores": { + "caps": 2, + "caps_strategy": "*busy", }, diff --git a/data/conf/samples/conc_reqs_queue/cgrates.json b/data/conf/samples/conc_reqs_queue/cgrates.json index 300b02506..3b3886f5b 100644 --- a/data/conf/samples/conc_reqs_queue/cgrates.json +++ b/data/conf/samples/conc_reqs_queue/cgrates.json @@ -4,8 +4,12 @@ "log_level": 7, "node_id": "ConcurrentQueueEngine", "reply_timeout": "50s", - "concurrent_requests": 2, - "concurrent_strategy": "*queue", +}, + + +"cores": { + "caps": 2, + "caps_strategy": "*queue", }, diff --git a/data/conf/samples/conc_reqs_queue_bench/cgrates.json b/data/conf/samples/conc_reqs_queue_bench/cgrates.json index 140a9cf61..a30533b6d 100644 --- a/data/conf/samples/conc_reqs_queue_bench/cgrates.json +++ b/data/conf/samples/conc_reqs_queue_bench/cgrates.json @@ -4,8 +4,12 @@ "log_level": 7, "node_id": "ConcurrentQueueEngine", "reply_timeout": "50s", - "concurrent_requests": 1000000, - "concurrent_strategy": "*queue" +}, + + +"cores": { + "caps": 1000000, + "caps_strategy": "*queue", }, diff --git a/dispatchers/caches_it_test.go b/dispatchers/caches_it_test.go index 76a10af96..496fb955b 100644 --- a/dispatchers/caches_it_test.go +++ b/dispatchers/caches_it_test.go @@ -213,6 +213,7 @@ func testDspChcPrecacheStatus(t *testing.T) { utils.CacheDispatchers: utils.MetaReady, utils.CacheEventCharges: utils.MetaReady, utils.CacheReverseFilterIndexes: utils.MetaReady, + utils.CacheCapsEvents: utils.MetaReady, utils.CacheAccounts: utils.MetaReady, utils.CacheVersions: utils.MetaReady, diff --git a/engine/cdrs.go b/engine/cdrs.go index 3cdf20361..5282f43b9 100644 --- a/engine/cdrs.go +++ b/engine/cdrs.go @@ -116,7 +116,7 @@ func (cdrS *CDRServer) ListenAndServe(stopChan chan struct{}) (err error) { } // RegisterHandlersToServer is called by cgr-engine to register HTTP URL handlers -func (cdrS *CDRServer) RegisterHandlersToServer(server *utils.Server) { +func (cdrS *CDRServer) RegisterHandlersToServer(server utils.Server) { server.RegisterHttpFunc(cdrS.cgrCfg.HTTPCfg().HTTPCDRsURL, cdrS.cgrCdrHandler) server.RegisterHttpFunc(cdrS.cgrCfg.HTTPCfg().HTTPFreeswitchCDRsURL, cdrS.fsCdrHandler) } diff --git a/engine/libtest.go b/engine/libtest.go index f163e279a..e4e7fa14f 100644 --- a/engine/libtest.go +++ b/engine/libtest.go @@ -521,6 +521,7 @@ func GetDefaultEmptyCacheStats() map[string]*ltcache.CacheStats { utils.CacheEventCharges: {}, utils.CacheReverseFilterIndexes: {}, utils.MetaAPIBan: {}, + utils.CacheCapsEvents: {}, utils.CacheAccounts: {}, utils.CacheVersions: {}, diff --git a/engine/routes.go b/engine/routes.go index 8936bad06..91051078b 100644 --- a/engine/routes.go +++ b/engine/routes.go @@ -604,14 +604,14 @@ func (attr *ArgsGetRoutes) Clone() *ArgsGetRoutes { } } -func (args *ArgsGetRoutes) asOptsGetRoutes() (opts *optsGetRoutes, err error) { - opts = &optsGetRoutes{ignoreErrors: args.IgnoreErrors} - if args.MaxCost == utils.MetaEventCost { // dynamic cost needs to be calculated from event - if err = args.CGREvent.CheckMandatoryFields([]string{utils.Account, +func (attr *ArgsGetRoutes) asOptsGetRoutes() (opts *optsGetRoutes, err error) { + opts = &optsGetRoutes{ignoreErrors: attr.IgnoreErrors} + if attr.MaxCost == utils.MetaEventCost { // dynamic cost needs to be calculated from event + if err = attr.CGREvent.CheckMandatoryFields([]string{utils.Account, utils.Destination, utils.SetupTime, utils.Usage}); err != nil { return } - cd, err := NewCallDescriptorFromCGREvent(args.CGREvent, + cd, err := NewCallDescriptorFromCGREvent(attr.CGREvent, config.CgrConfig().GeneralCfg().DefaultTimezone) if err != nil { return nil, err @@ -621,8 +621,8 @@ func (args *ArgsGetRoutes) asOptsGetRoutes() (opts *optsGetRoutes, err error) { return nil, err } opts.maxCost = cc.Cost - } else if args.MaxCost != "" { - if opts.maxCost, err = strconv.ParseFloat(args.MaxCost, + } else if attr.MaxCost != "" { + if opts.maxCost, err = strconv.ParseFloat(attr.MaxCost, 64); err != nil { return nil, err } diff --git a/engine/safevent.go b/engine/safevent.go index 02f02fdd9..76fe0b28b 100644 --- a/engine/safevent.go +++ b/engine/safevent.go @@ -119,7 +119,7 @@ func (se *SafEvent) GetString(fldName string) (out string, err error) { return } -func (se SafEvent) GetTInt64(fldName string) (out int64, err error) { +func (se *SafEvent) GetTInt64(fldName string) (out int64, err error) { se.RLock() out, err = se.Me.GetTInt64(fldName) se.RUnlock() diff --git a/engine/sharedgroup.go b/engine/sharedgroup.go index 8c1975c63..66778f608 100644 --- a/engine/sharedgroup.go +++ b/engine/sharedgroup.go @@ -70,7 +70,7 @@ func (sg *SharedGroup) Clone() (sharedGroup *SharedGroup) { if sg.MemberIds != nil { sharedGroup.MemberIds = sg.MemberIds.Clone() } - for id, _ := range sg.AccountParameters { + for id := range sg.AccountParameters { sharedGroup.AccountParameters[id] = sg.AccountParameters[id].Clone() } return diff --git a/packages/debian/changelog b/packages/debian/changelog index b7f79001d..13ceec4f0 100644 --- a/packages/debian/changelog +++ b/packages/debian/changelog @@ -123,6 +123,7 @@ cgrates (0.11.0~dev) UNRELEASED; urgency=medium * [AccountS] Add Initial in AccountSummary as initail value before debit operation * [General] For only *asap actions don't save AccountIDs withing ActionPlans * [AnalyzerS] Added AnalyzerSv1.StringQuery API to search over the recorded RPC calls + * [CoreS] Moved the server implementation in the new cores package -- DanB Wed, 19 Feb 2020 13:25:52 +0200 diff --git a/services/analyzers.go b/services/analyzers.go index 75f06bffc..0366ecb76 100644 --- a/services/analyzers.go +++ b/services/analyzers.go @@ -20,19 +20,18 @@ package services import ( "fmt" - "net" - "net/rpc" "sync" "github.com/cgrates/cgrates/analyzers" v1 "github.com/cgrates/cgrates/apier/v1" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/utils" "github.com/cgrates/rpcclient" ) // NewAnalyzerService returns the Analyzer Service -func NewAnalyzerService(cfg *config.CGRConfig, server *utils.Server, exitChan chan bool, +func NewAnalyzerService(cfg *config.CGRConfig, server *cores.Server, exitChan chan bool, internalAnalyzerSChan chan rpcclient.ClientConnector) *AnalyzerService { return &AnalyzerService{ connChan: internalAnalyzerSChan, @@ -46,7 +45,7 @@ func NewAnalyzerService(cfg *config.CGRConfig, server *utils.Server, exitChan ch type AnalyzerService struct { sync.RWMutex cfg *config.CGRConfig - server *utils.Server + server *cores.Server exitChan chan bool anz *analyzers.AnalyzerService @@ -71,17 +70,7 @@ func (anz *AnalyzerService) Start() (err error) { anz.exitChan <- true return }() - anz.server.SetAnzWrapperFunc(func(conn rpc.ServerCodec, enc string, from, to net.Addr) rpc.ServerCodec { - fromstr := "" - if from != nil { - fromstr = from.String() - } - tostr := "" - if to != nil { - tostr = to.String() - } - return anz.anz.NewServerCodec(conn, enc, fromstr, tostr) - }) + anz.server.SetAnalyzer(anz.anz) anz.rpc = v1.NewAnalyzerSv1(anz.anz) if !anz.cfg.DispatcherSCfg().Enabled { anz.server.RpcRegister(anz.rpc) @@ -99,6 +88,7 @@ func (anz *AnalyzerService) Reload() (err error) { // Shutdown stops the service func (anz *AnalyzerService) Shutdown() (err error) { anz.Lock() + anz.server.SetAnalyzer(nil) anz.anz.Shutdown() anz.anz = nil anz.rpc = nil diff --git a/services/apiers_it_test.go b/services/apiers_it_test.go index 1104c4386..2debae343 100644 --- a/services/apiers_it_test.go +++ b/services/apiers_it_test.go @@ -25,6 +25,7 @@ import ( "time" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -49,7 +50,7 @@ func TestApiersReload(t *testing.T) { cfg.ThresholdSCfg().Enabled = true cfg.SchedulerCfg().Enabled = true - server := utils.NewServer(nil) + server := cores.NewServer(nil) srvMngr := servmanager.NewServiceManager(cfg, engineShutdown) db := NewDataDBService(cfg, nil) cfg.StorDbCfg().Type = utils.INTERNAL diff --git a/services/apierv1.go b/services/apierv1.go index 412dd1e1f..0a5ec3559 100644 --- a/services/apierv1.go +++ b/services/apierv1.go @@ -25,6 +25,7 @@ import ( v1 "github.com/cgrates/cgrates/apier/v1" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/utils" "github.com/cgrates/rpcclient" @@ -33,7 +34,7 @@ import ( // NewAPIerSv1Service returns the APIerSv1 Service func NewAPIerSv1Service(cfg *config.CGRConfig, dm *DataDBService, storDB *StorDBService, filterSChan chan *engine.FilterS, - server *utils.Server, + server *cores.Server, schedService *SchedulerService, responderService *ResponderService, internalAPIerSv1Chan chan rpcclient.ClientConnector, @@ -61,7 +62,7 @@ type APIerSv1Service struct { dm *DataDBService storDB *StorDBService filterSChan chan *engine.FilterS - server *utils.Server + server *cores.Server schedService *SchedulerService responderService *ResponderService connMgr *engine.ConnManager diff --git a/services/apierv2.go b/services/apierv2.go index 12d73e607..0ed473958 100644 --- a/services/apierv2.go +++ b/services/apierv2.go @@ -23,13 +23,14 @@ import ( v2 "github.com/cgrates/cgrates/apier/v2" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/utils" "github.com/cgrates/rpcclient" ) // NewAPIerSv2Service returns the APIerSv2 Service func NewAPIerSv2Service(apiv1 *APIerSv1Service, cfg *config.CGRConfig, - server *utils.Server, + server *cores.Server, internalAPIerSv2Chan chan rpcclient.ClientConnector, anz *AnalyzerService) *APIerSv2Service { return &APIerSv2Service{ @@ -45,7 +46,7 @@ func NewAPIerSv2Service(apiv1 *APIerSv1Service, cfg *config.CGRConfig, type APIerSv2Service struct { sync.RWMutex cfg *config.CGRConfig - server *utils.Server + server *cores.Server apiv1 *APIerSv1Service api *v2.APIerSv2 diff --git a/services/attributes.go b/services/attributes.go index 589160237..2a1eddb6c 100644 --- a/services/attributes.go +++ b/services/attributes.go @@ -24,6 +24,7 @@ import ( v1 "github.com/cgrates/cgrates/apier/v1" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -33,7 +34,7 @@ import ( // NewAttributeService returns the Attribute Service func NewAttributeService(cfg *config.CGRConfig, dm *DataDBService, cacheS *engine.CacheS, filterSChan chan *engine.FilterS, - server *utils.Server, internalChan chan rpcclient.ClientConnector, + server *cores.Server, internalChan chan rpcclient.ClientConnector, anz *AnalyzerService) servmanager.Service { return &AttributeService{ connChan: internalChan, @@ -53,7 +54,7 @@ type AttributeService struct { dm *DataDBService cacheS *engine.CacheS filterSChan chan *engine.FilterS - server *utils.Server + server *cores.Server attrS *engine.AttributeService rpc *v1.AttributeSv1 // useful on restart diff --git a/services/attributes_it_test.go b/services/attributes_it_test.go index 1b12bfe01..fdec64f08 100644 --- a/services/attributes_it_test.go +++ b/services/attributes_it_test.go @@ -27,6 +27,7 @@ import ( "github.com/cgrates/rpcclient" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -46,7 +47,7 @@ func TestAttributeSReload(t *testing.T) { filterSChan <- nil close(chS.GetPrecacheChannel(utils.CacheAttributeProfiles)) close(chS.GetPrecacheChannel(utils.CacheAttributeFilterIndexes)) - server := utils.NewServer(nil) + server := cores.NewServer(nil) srvMngr := servmanager.NewServiceManager(cfg, engineShutdown) db := NewDataDBService(cfg, nil) attrRPC := make(chan rpcclient.ClientConnector, 1) diff --git a/services/cdrs.go b/services/cdrs.go index b37b74cff..1bb975e0d 100644 --- a/services/cdrs.go +++ b/services/cdrs.go @@ -26,6 +26,7 @@ import ( v1 "github.com/cgrates/cgrates/apier/v1" v2 "github.com/cgrates/cgrates/apier/v2" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -35,7 +36,7 @@ import ( // NewCDRServer returns the CDR Server func NewCDRServer(cfg *config.CGRConfig, dm *DataDBService, storDB *StorDBService, filterSChan chan *engine.FilterS, - server *utils.Server, internalCDRServerChan chan rpcclient.ClientConnector, + server *cores.Server, internalCDRServerChan chan rpcclient.ClientConnector, connMgr *engine.ConnManager, anz *AnalyzerService) servmanager.Service { return &CDRServer{ @@ -57,7 +58,7 @@ type CDRServer struct { dm *DataDBService storDB *StorDBService filterSChan chan *engine.FilterS - server *utils.Server + server *cores.Server cdrS *engine.CDRServer rpcv1 *v1.CDRsV1 diff --git a/services/cdrs_it_test.go b/services/cdrs_it_test.go index 35c46f6d4..1691784c9 100644 --- a/services/cdrs_it_test.go +++ b/services/cdrs_it_test.go @@ -25,6 +25,7 @@ import ( "time" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -58,7 +59,7 @@ func TestCdrsReload(t *testing.T) { close(chS.GetPrecacheChannel(utils.CacheTimings)) cfg.ChargerSCfg().Enabled = true - server := utils.NewServer(nil) + server := cores.NewServer(nil) srvMngr := servmanager.NewServiceManager(cfg, engineShutdown) db := NewDataDBService(cfg, nil) cfg.StorDbCfg().Type = utils.INTERNAL diff --git a/services/chargers.go b/services/chargers.go index 3f2728b9e..6f9fdef87 100644 --- a/services/chargers.go +++ b/services/chargers.go @@ -24,6 +24,7 @@ import ( v1 "github.com/cgrates/cgrates/apier/v1" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -32,7 +33,7 @@ import ( // NewChargerService returns the Charger Service func NewChargerService(cfg *config.CGRConfig, dm *DataDBService, - cacheS *engine.CacheS, filterSChan chan *engine.FilterS, server *utils.Server, + cacheS *engine.CacheS, filterSChan chan *engine.FilterS, server *cores.Server, internalChargerSChan chan rpcclient.ClientConnector, connMgr *engine.ConnManager, anz *AnalyzerService) servmanager.Service { return &ChargerService{ @@ -54,7 +55,7 @@ type ChargerService struct { dm *DataDBService cacheS *engine.CacheS filterSChan chan *engine.FilterS - server *utils.Server + server *cores.Server connMgr *engine.ConnManager chrS *engine.ChargerService diff --git a/services/chargers_it_test.go b/services/chargers_it_test.go index 4c2a311b0..033f3a9e2 100644 --- a/services/chargers_it_test.go +++ b/services/chargers_it_test.go @@ -27,6 +27,7 @@ import ( "github.com/cgrates/rpcclient" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -48,7 +49,7 @@ func TestChargerSReload(t *testing.T) { close(chS.GetPrecacheChannel(utils.CacheChargerFilterIndexes)) filterSChan := make(chan *engine.FilterS, 1) filterSChan <- nil - server := utils.NewServer(nil) + server := cores.NewServer(nil) srvMngr := servmanager.NewServiceManager(cfg, engineShutdown) db := NewDataDBService(cfg, nil) anz := NewAnalyzerService(cfg, server, engineShutdown, make(chan rpcclient.ClientConnector, 1)) diff --git a/services/datadb_it_test.go b/services/datadb_it_test.go index a2c10e420..728af7051 100644 --- a/services/datadb_it_test.go +++ b/services/datadb_it_test.go @@ -28,6 +28,7 @@ import ( "github.com/cgrates/rpcclient" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -47,7 +48,7 @@ func TestDataDBReload(t *testing.T) { filterSChan <- nil close(chS.GetPrecacheChannel(utils.CacheAttributeProfiles)) close(chS.GetPrecacheChannel(utils.CacheAttributeFilterIndexes)) - server := utils.NewServer(nil) + server := cores.NewServer(nil) srvMngr := servmanager.NewServiceManager(cfg, engineShutdown) cM := engine.NewConnManager(cfg, nil) db := NewDataDBService(cfg, cM) diff --git a/services/dispatcherh.go b/services/dispatcherh.go index e37a15079..c3375f8ee 100644 --- a/services/dispatcherh.go +++ b/services/dispatcherh.go @@ -22,6 +22,7 @@ import ( "sync" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/dispatcherh" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" @@ -30,7 +31,7 @@ import ( ) // NewDispatcherHostsService returns the Dispatcher Service -func NewDispatcherHostsService(cfg *config.CGRConfig, server *utils.Server, +func NewDispatcherHostsService(cfg *config.CGRConfig, server *cores.Server, internalChan chan rpcclient.ClientConnector, connMgr *engine.ConnManager, exitChan chan bool, anz *AnalyzerService) servmanager.Service { @@ -48,7 +49,7 @@ func NewDispatcherHostsService(cfg *config.CGRConfig, server *utils.Server, type DispatcherHostsService struct { sync.RWMutex cfg *config.CGRConfig - server *utils.Server + server *cores.Server connMgr *engine.ConnManager exitChan chan bool diff --git a/services/dispatchers.go b/services/dispatchers.go index 9f080a4d6..efc60a208 100644 --- a/services/dispatchers.go +++ b/services/dispatchers.go @@ -25,6 +25,7 @@ import ( v1 "github.com/cgrates/cgrates/apier/v1" v2 "github.com/cgrates/cgrates/apier/v2" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/dispatchers" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" @@ -35,7 +36,7 @@ import ( // NewDispatcherService returns the Dispatcher Service func NewDispatcherService(cfg *config.CGRConfig, dm *DataDBService, cacheS *engine.CacheS, filterSChan chan *engine.FilterS, - server *utils.Server, internalChan chan rpcclient.ClientConnector, + server *cores.Server, internalChan chan rpcclient.ClientConnector, connMgr *engine.ConnManager, anz *AnalyzerService) servmanager.Service { return &DispatcherService{ @@ -57,7 +58,7 @@ type DispatcherService struct { dm *DataDBService cacheS *engine.CacheS filterSChan chan *engine.FilterS - server *utils.Server + server *cores.Server connMgr *engine.ConnManager dspS *dispatchers.DispatcherService diff --git a/services/dispatchers_it_test.go b/services/dispatchers_it_test.go index 19de65281..c4ca98d1c 100644 --- a/services/dispatchers_it_test.go +++ b/services/dispatchers_it_test.go @@ -27,6 +27,7 @@ import ( "github.com/cgrates/rpcclient" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -49,7 +50,7 @@ func TestDispatcherSReload(t *testing.T) { close(chS.GetPrecacheChannel(utils.CacheDispatcherFilterIndexes)) filterSChan := make(chan *engine.FilterS, 1) filterSChan <- nil - server := utils.NewServer(nil) + server := cores.NewServer(nil) srvMngr := servmanager.NewServiceManager(cfg, engineShutdown) db := NewDataDBService(cfg, nil) anz := NewAnalyzerService(cfg, server, engineShutdown, make(chan rpcclient.ClientConnector, 1)) diff --git a/services/dnsagent_it_test.go b/services/dnsagent_it_test.go index 45fbfc76d..e186d24ab 100644 --- a/services/dnsagent_it_test.go +++ b/services/dnsagent_it_test.go @@ -25,6 +25,7 @@ import ( "time" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -47,7 +48,7 @@ func TestDNSAgentReload(t *testing.T) { cacheSChan := make(chan rpcclient.ClientConnector, 1) cacheSChan <- chS - server := utils.NewServer(nil) + server := cores.NewServer(nil) srvMngr := servmanager.NewServiceManager(cfg, engineShutdown) db := NewDataDBService(cfg, nil) anz := NewAnalyzerService(cfg, server, engineShutdown, make(chan rpcclient.ClientConnector, 1)) diff --git a/services/ees.go b/services/ees.go index 04d7247cf..922dfb5f1 100644 --- a/services/ees.go +++ b/services/ees.go @@ -24,6 +24,7 @@ import ( v1 "github.com/cgrates/cgrates/apier/v1" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/ees" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" @@ -33,7 +34,7 @@ import ( // NewEventExporterService constructs EventExporterService func NewEventExporterService(cfg *config.CGRConfig, filterSChan chan *engine.FilterS, - connMgr *engine.ConnManager, server *utils.Server, exitChan chan bool, + connMgr *engine.ConnManager, server *cores.Server, exitChan chan bool, intConnChan chan rpcclient.ClientConnector, anz *AnalyzerService) servmanager.Service { return &EventExporterService{ @@ -55,7 +56,7 @@ type EventExporterService struct { cfg *config.CGRConfig filterSChan chan *engine.FilterS connMgr *engine.ConnManager - server *utils.Server + server *cores.Server exitChan chan bool intConnChan chan rpcclient.ClientConnector rldChan chan struct{} diff --git a/services/ees_it_test.go b/services/ees_it_test.go index 32ae43879..737c763ec 100644 --- a/services/ees_it_test.go +++ b/services/ees_it_test.go @@ -28,6 +28,7 @@ import ( "github.com/cgrates/rpcclient" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -53,7 +54,7 @@ func TestEventExporterSReload(t *testing.T) { filterSChan := make(chan *engine.FilterS, 1) filterSChan <- nil engineShutdown := make(chan bool, 1) - server := utils.NewServer(nil) + server := cores.NewServer(nil) srvMngr := servmanager.NewServiceManager(cfg, engineShutdown) db := NewDataDBService(cfg, nil) chS := engine.NewCacheS(cfg, nil) diff --git a/services/ers_it_test.go b/services/ers_it_test.go index 02d53947c..542a6e805 100644 --- a/services/ers_it_test.go +++ b/services/ers_it_test.go @@ -28,6 +28,7 @@ import ( "github.com/cgrates/rpcclient" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -52,7 +53,7 @@ func TestEventReaderSReload(t *testing.T) { filterSChan := make(chan *engine.FilterS, 1) filterSChan <- nil engineShutdown := make(chan bool, 1) - server := utils.NewServer(nil) + server := cores.NewServer(nil) srvMngr := servmanager.NewServiceManager(cfg, engineShutdown) anz := NewAnalyzerService(cfg, server, engineShutdown, make(chan rpcclient.ClientConnector, 1)) db := NewDataDBService(cfg, nil) diff --git a/services/httpagent.go b/services/httpagent.go index b9175b0fe..869b14850 100644 --- a/services/httpagent.go +++ b/services/httpagent.go @@ -24,6 +24,7 @@ import ( "github.com/cgrates/cgrates/agents" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -31,7 +32,7 @@ import ( // NewHTTPAgent returns the HTTP Agent func NewHTTPAgent(cfg *config.CGRConfig, filterSChan chan *engine.FilterS, - server *utils.Server, connMgr *engine.ConnManager) servmanager.Service { + server *cores.Server, connMgr *engine.ConnManager) servmanager.Service { return &HTTPAgent{ cfg: cfg, filterSChan: filterSChan, @@ -45,7 +46,7 @@ type HTTPAgent struct { sync.RWMutex cfg *config.CGRConfig filterSChan chan *engine.FilterS - server *utils.Server + server *cores.Server ha *agents.HTTPAgent connMgr *engine.ConnManager diff --git a/services/loaders.go b/services/loaders.go index b42959860..1cda4769d 100644 --- a/services/loaders.go +++ b/services/loaders.go @@ -23,6 +23,7 @@ import ( v1 "github.com/cgrates/cgrates/apier/v1" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/loaders" "github.com/cgrates/cgrates/utils" @@ -31,7 +32,7 @@ import ( // NewLoaderService returns the Loader Service func NewLoaderService(cfg *config.CGRConfig, dm *DataDBService, - filterSChan chan *engine.FilterS, server *utils.Server, + filterSChan chan *engine.FilterS, server *cores.Server, exitChan chan bool, internalLoaderSChan chan rpcclient.ClientConnector, connMgr *engine.ConnManager, anz *AnalyzerService) *LoaderService { @@ -53,7 +54,7 @@ type LoaderService struct { cfg *config.CGRConfig dm *DataDBService filterSChan chan *engine.FilterS - server *utils.Server + server *cores.Server exitChan chan bool ldrs *loaders.LoaderService diff --git a/services/rals.go b/services/rals.go index 19600e82a..64576c82e 100644 --- a/services/rals.go +++ b/services/rals.go @@ -23,6 +23,7 @@ import ( v1 "github.com/cgrates/cgrates/apier/v1" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -30,7 +31,7 @@ import ( ) // NewRalService returns the Ral Service -func NewRalService(cfg *config.CGRConfig, cacheS *engine.CacheS, server *utils.Server, +func NewRalService(cfg *config.CGRConfig, cacheS *engine.CacheS, server *cores.Server, internalRALsChan, internalResponderChan chan rpcclient.ClientConnector, exitChan chan bool, connMgr *engine.ConnManager, anz *AnalyzerService) *RalService { @@ -52,7 +53,7 @@ type RalService struct { sync.RWMutex cfg *config.CGRConfig cacheS *engine.CacheS - server *utils.Server + server *cores.Server rals *v1.RALsV1 responder *ResponderService connChan chan rpcclient.ClientConnector diff --git a/services/rals_it_test.go b/services/rals_it_test.go index 7c87ad3fc..7afc09c5e 100644 --- a/services/rals_it_test.go +++ b/services/rals_it_test.go @@ -25,6 +25,7 @@ import ( "time" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -58,7 +59,7 @@ func TestRalsReload(t *testing.T) { close(chS.GetPrecacheChannel(utils.CacheTimings)) cfg.ThresholdSCfg().Enabled = true - server := utils.NewServer(nil) + server := cores.NewServer(nil) srvMngr := servmanager.NewServiceManager(cfg, engineShutdown) db := NewDataDBService(cfg, nil) cfg.StorDbCfg().Type = utils.INTERNAL diff --git a/services/rates.go b/services/rates.go index 2e62aeed6..14b8bf668 100644 --- a/services/rates.go +++ b/services/rates.go @@ -23,6 +23,7 @@ import ( "sync" v1 "github.com/cgrates/cgrates/apier/v1" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/engine" @@ -39,7 +40,7 @@ func NewRateService( cfg *config.CGRConfig, cacheS *engine.CacheS, filterSChan chan *engine.FilterS, dmS *DataDBService, - server *utils.Server, exitChan chan bool, + server *cores.Server, exitChan chan bool, intConnChan chan rpcclient.ClientConnector, anz *AnalyzerService) servmanager.Service { return &RateService{ @@ -63,7 +64,7 @@ type RateService struct { filterSChan chan *engine.FilterS dmS *DataDBService cacheS *engine.CacheS - server *utils.Server + server *cores.Server exitChan chan bool rldChan chan struct{} diff --git a/services/rates_it_test.go b/services/rates_it_test.go index c5602a238..c598af80a 100644 --- a/services/rates_it_test.go +++ b/services/rates_it_test.go @@ -27,6 +27,7 @@ import ( "github.com/cgrates/rpcclient" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -42,7 +43,7 @@ func TestRateSReload(t *testing.T) { filterSChan := make(chan *engine.FilterS, 1) filterSChan <- nil engineShutdown := make(chan bool, 1) - server := utils.NewServer(nil) + server := cores.NewServer(nil) srvMngr := servmanager.NewServiceManager(cfg, engineShutdown) db := NewDataDBService(cfg, nil) chS := engine.NewCacheS(cfg, nil) diff --git a/services/resources.go b/services/resources.go index 8222f1a45..d2afca694 100644 --- a/services/resources.go +++ b/services/resources.go @@ -24,6 +24,7 @@ import ( v1 "github.com/cgrates/cgrates/apier/v1" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -33,7 +34,7 @@ import ( // NewResourceService returns the Resource Service func NewResourceService(cfg *config.CGRConfig, dm *DataDBService, cacheS *engine.CacheS, filterSChan chan *engine.FilterS, - server *utils.Server, internalResourceSChan chan rpcclient.ClientConnector, + server *cores.Server, internalResourceSChan chan rpcclient.ClientConnector, connMgr *engine.ConnManager, anz *AnalyzerService) servmanager.Service { return &ResourceService{ @@ -55,7 +56,7 @@ type ResourceService struct { dm *DataDBService cacheS *engine.CacheS filterSChan chan *engine.FilterS - server *utils.Server + server *cores.Server reS *engine.ResourceService rpc *v1.ResourceSv1 diff --git a/services/resources_it_test.go b/services/resources_it_test.go index 603f94d87..7fed5e2d7 100644 --- a/services/resources_it_test.go +++ b/services/resources_it_test.go @@ -27,6 +27,7 @@ import ( "github.com/cgrates/rpcclient" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -51,7 +52,7 @@ func TestResourceSReload(t *testing.T) { close(chS.GetPrecacheChannel(utils.CacheResourceProfiles)) close(chS.GetPrecacheChannel(utils.CacheResources)) close(chS.GetPrecacheChannel(utils.CacheResourceFilterIndexes)) - server := utils.NewServer(nil) + server := cores.NewServer(nil) srvMngr := servmanager.NewServiceManager(cfg, engineShutdown) anz := NewAnalyzerService(cfg, server, engineShutdown, make(chan rpcclient.ClientConnector, 1)) db := NewDataDBService(cfg, nil) diff --git a/services/responders.go b/services/responders.go index 6f952b293..ae12a5203 100644 --- a/services/responders.go +++ b/services/responders.go @@ -22,13 +22,14 @@ import ( "sync" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/utils" "github.com/cgrates/rpcclient" ) // NewResponderService returns the Resonder Service -func NewResponderService(cfg *config.CGRConfig, server *utils.Server, +func NewResponderService(cfg *config.CGRConfig, server *cores.Server, internalRALsChan chan rpcclient.ClientConnector, exitChan chan bool, anz *AnalyzerService) *ResponderService { return &ResponderService{ @@ -44,7 +45,7 @@ func NewResponderService(cfg *config.CGRConfig, server *utils.Server, type ResponderService struct { sync.RWMutex cfg *config.CGRConfig - server *utils.Server + server *cores.Server exitChan chan bool resp *engine.Responder diff --git a/services/routes.go b/services/routes.go index 54fd98941..540cd7448 100644 --- a/services/routes.go +++ b/services/routes.go @@ -24,6 +24,7 @@ import ( v1 "github.com/cgrates/cgrates/apier/v1" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -33,7 +34,7 @@ import ( // NewRouteService returns the Route Service func NewRouteService(cfg *config.CGRConfig, dm *DataDBService, cacheS *engine.CacheS, filterSChan chan *engine.FilterS, - server *utils.Server, internalRouteSChan chan rpcclient.ClientConnector, + server *cores.Server, internalRouteSChan chan rpcclient.ClientConnector, connMgr *engine.ConnManager, anz *AnalyzerService) servmanager.Service { return &RouteService{ @@ -55,7 +56,7 @@ type RouteService struct { dm *DataDBService cacheS *engine.CacheS filterSChan chan *engine.FilterS - server *utils.Server + server *cores.Server connMgr *engine.ConnManager routeS *engine.RouteService diff --git a/services/routes_it_test.go b/services/routes_it_test.go index 482f89d57..8ac6d4fc7 100644 --- a/services/routes_it_test.go +++ b/services/routes_it_test.go @@ -27,6 +27,7 @@ import ( "github.com/cgrates/rpcclient" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -49,7 +50,7 @@ func TestSupplierSReload(t *testing.T) { close(chS.GetPrecacheChannel(utils.CacheStatQueueProfiles)) close(chS.GetPrecacheChannel(utils.CacheStatQueues)) close(chS.GetPrecacheChannel(utils.CacheStatFilterIndexes)) - server := utils.NewServer(nil) + server := cores.NewServer(nil) srvMngr := servmanager.NewServiceManager(cfg, engineShutdown) db := NewDataDBService(cfg, nil) anz := NewAnalyzerService(cfg, server, engineShutdown, make(chan rpcclient.ClientConnector, 1)) diff --git a/services/schedulers.go b/services/schedulers.go index 34c188f82..6dfa99382 100644 --- a/services/schedulers.go +++ b/services/schedulers.go @@ -23,6 +23,7 @@ import ( v1 "github.com/cgrates/cgrates/apier/v1" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/scheduler" "github.com/cgrates/cgrates/utils" @@ -32,7 +33,7 @@ import ( // NewSchedulerService returns the Scheduler Service func NewSchedulerService(cfg *config.CGRConfig, dm *DataDBService, cacheS *engine.CacheS, fltrSChan chan *engine.FilterS, - server *utils.Server, internalSchedulerrSChan chan rpcclient.ClientConnector, + server *cores.Server, internalSchedulerrSChan chan rpcclient.ClientConnector, connMgr *engine.ConnManager, anz *AnalyzerService) *SchedulerService { return &SchedulerService{ @@ -54,7 +55,7 @@ type SchedulerService struct { dm *DataDBService cacheS *engine.CacheS fltrSChan chan *engine.FilterS - server *utils.Server + server *cores.Server schS *scheduler.Scheduler rpc *v1.SchedulerSv1 diff --git a/services/schedulers_it_test.go b/services/schedulers_it_test.go index c89f6fb7a..0d8c7390a 100644 --- a/services/schedulers_it_test.go +++ b/services/schedulers_it_test.go @@ -25,6 +25,7 @@ import ( "time" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -43,7 +44,7 @@ func TestSchedulerSReload(t *testing.T) { filterSChan := make(chan *engine.FilterS, 1) filterSChan <- nil close(chS.GetPrecacheChannel(utils.CacheActionPlans)) - server := utils.NewServer(nil) + server := cores.NewServer(nil) srvMngr := servmanager.NewServiceManager(cfg, engineShutdown) db := NewDataDBService(cfg, nil) anz := NewAnalyzerService(cfg, server, engineShutdown, make(chan rpcclient.ClientConnector, 1)) diff --git a/services/sessions.go b/services/sessions.go index a18cf9732..098029dca 100644 --- a/services/sessions.go +++ b/services/sessions.go @@ -22,6 +22,7 @@ import ( "fmt" "sync" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" v1 "github.com/cgrates/cgrates/apier/v1" @@ -34,9 +35,9 @@ import ( // NewSessionService returns the Session Service func NewSessionService(cfg *config.CGRConfig, dm *DataDBService, - server *utils.Server, internalChan chan rpcclient.ClientConnector, + server *cores.Server, internalChan chan rpcclient.ClientConnector, exitChan chan bool, connMgr *engine.ConnManager, - concReq *utils.ConcReqs, + caps *cores.Caps, anz *AnalyzerService) servmanager.Service { return &SessionService{ connChan: internalChan, @@ -45,7 +46,7 @@ func NewSessionService(cfg *config.CGRConfig, dm *DataDBService, server: server, exitChan: exitChan, connMgr: connMgr, - concReq: concReq, + caps: caps, anz: anz, } } @@ -55,7 +56,7 @@ type SessionService struct { sync.RWMutex cfg *config.CGRConfig dm *DataDBService - server *utils.Server + server *cores.Server exitChan chan bool sm *sessions.SessionS @@ -66,7 +67,7 @@ type SessionService struct { // in order to stop the bircp server if necesary bircpEnabled bool connMgr *engine.ConnManager - concReq *utils.ConcReqs + caps *cores.Caps anz *AnalyzerService } @@ -90,9 +91,9 @@ func (smg *SessionService) Start() (err error) { // Pass internal connection via BiRPCClient smg.connChan <- smg.anz.GetInternalCodec(smg.sm, utils.SessionS) // Register RPC handler - smg.rpc = v1.NewSMGenericV1(smg.sm, smg.concReq) + smg.rpc = v1.NewSMGenericV1(smg.sm, smg.caps) - smg.rpcv1 = v1.NewSessionSv1(smg.sm, smg.concReq) // methods with multiple options + smg.rpcv1 = v1.NewSessionSv1(smg.sm, smg.caps) // methods with multiple options if !smg.cfg.DispatcherSCfg().Enabled { smg.server.RpcRegister(smg.rpc) smg.server.RpcRegister(smg.rpcv1) diff --git a/services/sessions_it_test.go b/services/sessions_it_test.go index 08c71291f..31f1b29c5 100644 --- a/services/sessions_it_test.go +++ b/services/sessions_it_test.go @@ -25,6 +25,7 @@ import ( "time" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -65,7 +66,7 @@ func TestSessionSReload(t *testing.T) { cacheSChan := make(chan rpcclient.ClientConnector, 1) cacheSChan <- chS - server := utils.NewServer(nil) + server := cores.NewServer(nil) srvMngr := servmanager.NewServiceManager(cfg, engineShutdown) db := NewDataDBService(cfg, nil) cfg.StorDbCfg().Type = utils.INTERNAL diff --git a/services/sipagent_it_test.go b/services/sipagent_it_test.go index 4bfc88393..0997dc2bf 100644 --- a/services/sipagent_it_test.go +++ b/services/sipagent_it_test.go @@ -25,6 +25,7 @@ import ( "time" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -47,7 +48,7 @@ func TestSIPAgentReload(t *testing.T) { cacheSChan := make(chan rpcclient.ClientConnector, 1) cacheSChan <- chS - server := utils.NewServer(nil) + server := cores.NewServer(nil) srvMngr := servmanager.NewServiceManager(cfg, engineShutdown) db := NewDataDBService(cfg, nil) anz := NewAnalyzerService(cfg, server, engineShutdown, make(chan rpcclient.ClientConnector, 1)) diff --git a/services/stats.go b/services/stats.go index 2e8c54f97..2957e9c24 100644 --- a/services/stats.go +++ b/services/stats.go @@ -24,6 +24,7 @@ import ( v1 "github.com/cgrates/cgrates/apier/v1" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -33,7 +34,7 @@ import ( // NewStatService returns the Stat Service func NewStatService(cfg *config.CGRConfig, dm *DataDBService, cacheS *engine.CacheS, filterSChan chan *engine.FilterS, - server *utils.Server, internalStatSChan chan rpcclient.ClientConnector, + server *cores.Server, internalStatSChan chan rpcclient.ClientConnector, connMgr *engine.ConnManager, anz *AnalyzerService) servmanager.Service { return &StatService{ @@ -55,7 +56,7 @@ type StatService struct { dm *DataDBService cacheS *engine.CacheS filterSChan chan *engine.FilterS - server *utils.Server + server *cores.Server connMgr *engine.ConnManager sts *engine.StatService diff --git a/services/stats_it_test.go b/services/stats_it_test.go index c399cd67e..81fc69f03 100644 --- a/services/stats_it_test.go +++ b/services/stats_it_test.go @@ -27,6 +27,7 @@ import ( "github.com/cgrates/rpcclient" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -51,7 +52,7 @@ func TestStatSReload(t *testing.T) { close(chS.GetPrecacheChannel(utils.CacheStatQueueProfiles)) close(chS.GetPrecacheChannel(utils.CacheStatQueues)) close(chS.GetPrecacheChannel(utils.CacheStatFilterIndexes)) - server := utils.NewServer(nil) + server := cores.NewServer(nil) srvMngr := servmanager.NewServiceManager(cfg, engineShutdown) anz := NewAnalyzerService(cfg, server, engineShutdown, make(chan rpcclient.ClientConnector, 1)) db := NewDataDBService(cfg, nil) diff --git a/services/thresholds.go b/services/thresholds.go index 548560f99..7ee72c653 100644 --- a/services/thresholds.go +++ b/services/thresholds.go @@ -24,6 +24,7 @@ import ( v1 "github.com/cgrates/cgrates/apier/v1" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -33,7 +34,7 @@ import ( // NewThresholdService returns the Threshold Service func NewThresholdService(cfg *config.CGRConfig, dm *DataDBService, cacheS *engine.CacheS, filterSChan chan *engine.FilterS, - server *utils.Server, internalThresholdSChan chan rpcclient.ClientConnector, + server *cores.Server, internalThresholdSChan chan rpcclient.ClientConnector, anz *AnalyzerService) servmanager.Service { return &ThresholdService{ connChan: internalThresholdSChan, @@ -53,7 +54,7 @@ type ThresholdService struct { dm *DataDBService cacheS *engine.CacheS filterSChan chan *engine.FilterS - server *utils.Server + server *cores.Server thrs *engine.ThresholdService rpc *v1.ThresholdSv1 diff --git a/services/thresholds_it_test.go b/services/thresholds_it_test.go index d807bb4cc..02c7ad665 100644 --- a/services/thresholds_it_test.go +++ b/services/thresholds_it_test.go @@ -25,6 +25,7 @@ import ( "time" "github.com/cgrates/cgrates/config" + "github.com/cgrates/cgrates/cores" "github.com/cgrates/cgrates/engine" "github.com/cgrates/cgrates/servmanager" "github.com/cgrates/cgrates/utils" @@ -46,7 +47,7 @@ func TestThresholdSReload(t *testing.T) { close(chS.GetPrecacheChannel(utils.CacheThresholdProfiles)) close(chS.GetPrecacheChannel(utils.CacheThresholds)) close(chS.GetPrecacheChannel(utils.CacheThresholdFilterIndexes)) - server := utils.NewServer(nil) + server := cores.NewServer(nil) srvMngr := servmanager.NewServiceManager(cfg, engineShutdown) anz := NewAnalyzerService(cfg, server, engineShutdown, make(chan rpcclient.ClientConnector, 1)) db := NewDataDBService(cfg, nil) diff --git a/utils/concureqs.go b/utils/concureqs.go deleted file mode 100644 index 64b8e8524..000000000 --- a/utils/concureqs.go +++ /dev/null @@ -1,184 +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 utils - -import ( - "net" - "net/rpc" - "net/rpc/jsonrpc" - "time" -) - -// ConcReqs the structure that allocs requests for API -type ConcReqs struct { - strategy string - aReqs chan struct{} - // st *concReqStats -} - -// NewConReqs creates a new ConcReqs -func NewConReqs(reqs int, strategy string, ttl, sampleinterval time.Duration, exitChan chan bool) *ConcReqs { - cR := &ConcReqs{ - strategy: strategy, - aReqs: make(chan struct{}, reqs), - } - /* - if ttl != 0 { - cR.st = newConcReqStatS(ttl, sampleinterval, exitChan, cR.aReqs) - }*/ - return cR -} - -// IsLimited returns true if the limit is not 0 -func (cR *ConcReqs) IsLimited() bool { - return cap(cR.aReqs) != 0 -} - -// Allocated returns the number of requests actively serviced -func (cR *ConcReqs) Allocated() int { - return len(cR.aReqs) -} - -// Allocate will reserve a channel for the API call -func (cR *ConcReqs) Allocate() (err error) { - switch cR.strategy { - case MetaBusy: - if len(cR.aReqs) == cap(cR.aReqs) { - return ErrMaxConcurentRPCExceededNoCaps - } - fallthrough - case MetaQueue: - cR.aReqs <- struct{}{} - } - return -} - -// Deallocate will free a channel for the API call -func (cR *ConcReqs) Deallocate() { - <-cR.aReqs - return -} - -type conn interface { - Read(b []byte) (n int, err error) - Write(b []byte) (n int, err error) - Close() error - LocalAddr() net.Addr - RemoteAddr() net.Addr -} - -func newConcReqsGOBCodec(conn conn, conReqs *ConcReqs, anz anzWrapFunc) rpc.ServerCodec { - return anz(newConcReqsServerCodec(newGobServerCodec(conn), conReqs), MetaGOB, conn.RemoteAddr(), conn.LocalAddr()) -} - -func newConcReqsJSONCodec(conn conn, conReqs *ConcReqs, anz anzWrapFunc) rpc.ServerCodec { - return anz(newConcReqsServerCodec(jsonrpc.NewServerCodec(conn), conReqs), MetaJSON, conn.RemoteAddr(), conn.LocalAddr()) -} - -func newConcReqsServerCodec(sc rpc.ServerCodec, conReqs *ConcReqs) rpc.ServerCodec { - if !conReqs.IsLimited() { - return sc - } - return &concReqsServerCodec{ - sc: sc, - conReqs: conReqs, - } -} - -type concReqsServerCodec struct { - sc rpc.ServerCodec - conReqs *ConcReqs -} - -func (c *concReqsServerCodec) ReadRequestHeader(r *rpc.Request) error { - return c.sc.ReadRequestHeader(r) -} - -func (c *concReqsServerCodec) ReadRequestBody(x interface{}) error { - if err := c.conReqs.Allocate(); err != nil { - return err - } - return c.sc.ReadRequestBody(x) -} -func (c *concReqsServerCodec) WriteResponse(r *rpc.Response, x interface{}) error { - if r.Error == ErrMaxConcurentRPCExceededNoCaps.Error() { - r.Error = ErrMaxConcurentRPCExceeded.Error() - } else { - defer c.conReqs.Deallocate() - } - return c.sc.WriteResponse(r, x) -} -func (c *concReqsServerCodec) Close() error { return c.sc.Close() } - -/* -func newConcReqStatS(ttl, sampleinterval time.Duration, exitChan chan bool, concReq chan struct{}) (cs *concReqStats) { - cs = &concReqStats{ - st: NewStatAverage(2), - } - cs.cache = ltcache.NewCache(-1, ttl, true, cs.onEvict) - go cs.loop(sampleinterval, exitChan, concReq) - return -} - -type concReqStats struct { - sync.RWMutex - cache *ltcache.Cache - st *StatAverage - peak int -} - -func (cs *concReqStats) onEvict(itmID string, value interface{}) { - cs.st.RemEvent(itmID) -} - -func (cs *concReqStats) loop(intr time.Duration, exitChan chan bool, concReq chan struct{}) { - for { - select { - case v := <-exitChan: - exitChan <- v - return - case <-time.After(intr): - evID := time.Now().String() - val := len(concReq) - - cs.Lock() - cs.cache.Set(evID, val, nil) - cs.st.AddStat(evID, float64(val)) - if val > cs.peak { - cs.peak = val - } - cs.Unlock() - } - } -} - -func (cs *concReqStats) GetPeak() (peak int) { - cs.RLock() - peak = cs.peak - cs.RUnlock() - return -} - -func (cs *concReqStats) GetAverage(roundingDecimals int) (avg float64) { - cs.RLock() - avg = cs.st.GetFloat64Value(roundingDecimals) - cs.RUnlock() - return -} -*/ diff --git a/utils/consts.go b/utils/consts.go index 3a583d966..b17215f4b 100755 --- a/utils/consts.go +++ b/utils/consts.go @@ -53,7 +53,7 @@ var ( CacheDispatcherRoutes, CacheDispatcherLoads, CacheDiameterMessages, CacheRPCResponses, CacheClosedSessions, CacheCDRIDs, CacheLoadIDs, CacheRPCConnections, CacheRatingProfilesTmp, CacheUCH, CacheSTIR, CacheEventCharges, CacheRateProfiles, CacheRateProfilesFilterIndexes, - CacheRateFilterIndexes, CacheReverseFilterIndexes, MetaAPIBan, + CacheRateFilterIndexes, CacheReverseFilterIndexes, MetaAPIBan, CacheCapsEvents, // only internalDB CacheVersions, CacheAccounts, CacheTBLTPTimings, CacheTBLTPDestinations, CacheTBLTPRates, CacheTBLTPDestinationRates, @@ -718,6 +718,7 @@ const ( MetaTrl = "*trl" MetaTmp = "*tmp" MetaOpts = "*opts" + MetaDynReq = "~*req" MetaScPrefix = "~*sc." // used for SMCostFilter CGROriginHost = "cgr_originhost" MetaInitiate = "*initiate" @@ -1801,6 +1802,7 @@ const ( CacheReverseFilterIndexes = "*reverse_filter_indexes" CacheAccounts = "*accounts" CacheVersions = "*versions" + CacheCapsEvents = "*caps_events" // storDB CacheTBLTPTimings = "*tp_timings" @@ -1874,32 +1876,30 @@ var ( // GeneralCfg const ( - NodeIDCfg = "node_id" - LoggerCfg = "logger" - LogLevelCfg = "log_level" - RoundingDecimalsCfg = "rounding_decimals" - DBDataEncodingCfg = "dbdata_encoding" - TpExportPathCfg = "tpexport_dir" - PosterAttemptsCfg = "poster_attempts" - FailedPostsDirCfg = "failed_posts_dir" - FailedPostsTTLCfg = "failed_posts_ttl" - DefaultReqTypeCfg = "default_request_type" - DefaultCategoryCfg = "default_category" - DefaultTenantCfg = "default_tenant" - DefaultTimezoneCfg = "default_timezone" - DefaultCachingCfg = "default_caching" - ConnectAttemptsCfg = "connect_attempts" - ReconnectsCfg = "reconnects" - ConnectTimeoutCfg = "connect_timeout" - ReplyTimeoutCfg = "reply_timeout" - LockingTimeoutCfg = "locking_timeout" - DigestSeparatorCfg = "digest_separator" - DigestEqualCfg = "digest_equal" - RSRSepCfg = "rsr_separator" - MaxParallelConnsCfg = "max_parallel_conns" - ConcurrentRequestsCfg = "concurrent_requests" - ConcurrentStrategyCfg = "concurrent_strategy" - EEsConnsCfg = "ees_conns" + NodeIDCfg = "node_id" + LoggerCfg = "logger" + LogLevelCfg = "log_level" + RoundingDecimalsCfg = "rounding_decimals" + DBDataEncodingCfg = "dbdata_encoding" + TpExportPathCfg = "tpexport_dir" + PosterAttemptsCfg = "poster_attempts" + FailedPostsDirCfg = "failed_posts_dir" + FailedPostsTTLCfg = "failed_posts_ttl" + DefaultReqTypeCfg = "default_request_type" + DefaultCategoryCfg = "default_category" + DefaultTenantCfg = "default_tenant" + DefaultTimezoneCfg = "default_timezone" + DefaultCachingCfg = "default_caching" + ConnectAttemptsCfg = "connect_attempts" + ReconnectsCfg = "reconnects" + ConnectTimeoutCfg = "connect_timeout" + ReplyTimeoutCfg = "reply_timeout" + LockingTimeoutCfg = "locking_timeout" + DigestSeparatorCfg = "digest_separator" + DigestEqualCfg = "digest_equal" + RSRSepCfg = "rsr_separator" + MaxParallelConnsCfg = "max_parallel_conns" + EEsConnsCfg = "ees_conns" ) // StorDbCfg @@ -1939,7 +1939,7 @@ const ( // ItemOpt const ( - ApiKeyCfg = "api_key" + APIKeyCfg = "api_key" RouteIDCfg = "route_id" RemoteCfg = "remote" ReplicateCfg = "replicate" @@ -2100,20 +2100,20 @@ const ( AsteriskConnsCfg = "asterisk_conns" // DiameterAgentCfg - ListenNetCfg = "listen_net" - ListenCfg = "listen" - DictionariesPathCfg = "dictionaries_path" - OriginHostCfg = "origin_host" - OriginRealmCfg = "origin_realm" - VendorIdCfg = "vendor_id" - ProductNameCfg = "product_name" - ConcurrentReqsCfg = "concurrent_requests" - SyncedConnReqsCfg = "synced_conn_requests" - ASRTemplateCfg = "asr_template" - RARTemplateCfg = "rar_template" - ForcedDisconnectCfg = "forced_disconnect" - TemplatesCfg = "templates" - RequestProcessorsCfg = "request_processors" + ListenNetCfg = "listen_net" + ConcurrentRequestsCfg = "concurrent_requests" + ListenCfg = "listen" + DictionariesPathCfg = "dictionaries_path" + OriginHostCfg = "origin_host" + OriginRealmCfg = "origin_realm" + VendorIDCfg = "vendor_id" + ProductNameCfg = "product_name" + SyncedConnReqsCfg = "synced_conn_requests" + ASRTemplateCfg = "asr_template" + RARTemplateCfg = "rar_template" + ForcedDisconnectCfg = "forced_disconnect" + TemplatesCfg = "templates" + RequestProcessorsCfg = "request_processors" // RequestProcessor RequestFieldsCfg = "request_fields" @@ -2149,24 +2149,23 @@ const ( AttributeIDsCfg = "attribute_ids" //LoaderSCfg - IdCfg = "id" DryRunCfg = "dry_run" LockFileNameCfg = "lock_filename" TpInDirCfg = "tp_in_dir" TpOutDirCfg = "tp_out_dir" DataCfg = "data" - DefaultRatioCfg = "default_ratio" - ReadersCfg = "readers" - ExportersCfg = "exporters" - PoolSize = "poolSize" - Conns = "conns" - FilenameCfg = "file_name" - RequestPayloadCfg = "request_payload" - ReplyPayloadCfg = "reply_payload" - TransportCfg = "transport" - StrategyCfg = "strategy" - Dynaprepaid_actionplansCfg = "dynaprepaid_actionplans" + DefaultRatioCfg = "default_ratio" + ReadersCfg = "readers" + ExportersCfg = "exporters" + PoolSize = "poolSize" + Conns = "conns" + FilenameCfg = "file_name" + RequestPayloadCfg = "request_payload" + ReplyPayloadCfg = "reply_payload" + TransportCfg = "transport" + StrategyCfg = "strategy" + DynaprepaidActionplansCfg = "dynaprepaid_actionplans" //RateSCfg RateIndexedSelectsCfg = "rate_indexed_selects" @@ -2179,6 +2178,11 @@ const ( CleanupIntervalCfg = "cleanup_interval" IndexTypeCfg = "index_type" DBPathCfg = "db_path" + + // CoreSCfg + CapsCfg = "caps" + CapsStrategyCfg = "caps_strategy" + CapsStatsIntervalCfg = "caps_stats_interval" ) // FC Template @@ -2195,7 +2199,7 @@ const ( NewBranchCfg = "new_branch" BlockerCfg = "blocker" BreakOnSuccessCfg = "break_on_success" - Handler_id = "handler_id" + HandlerIDCfg = "handler_id" LayoutCfg = "layout" CostShiftDigitsCfg = "cost_shift_digits" MaskDestIDCfg = "mask_destinationd_id" diff --git a/utils/dateseries.go b/utils/dateseries.go index ad1aa1657..7ec0391d3 100644 --- a/utils/dateseries.go +++ b/utils/dateseries.go @@ -20,7 +20,6 @@ package utils import ( "fmt" - "net" "reflect" "sort" "strconv" @@ -340,50 +339,3 @@ func DaysInYear(year int) float64 { last := first.AddDate(1, 0, 0) return float64(last.Sub(first).Hours() / 24) } - -func LocalAddr() *NetAddr { - return &NetAddr{network: Local, ip: Local} -} - -func NewNetAddr(network, host string) *NetAddr { - ip, port, err := net.SplitHostPort(host) - if err != nil { - Logger.Warning(fmt.Sprintf("failed parsing RemoteAddr: %s, err: %s", - host, err.Error())) - } - p, err := strconv.Atoi(port) - if err != nil { - Logger.Warning(fmt.Sprintf("failed converting port : %+v, err: %s", - port, err.Error())) - } - return &NetAddr{network: network, ip: ip, port: p} -} - -type NetAddr struct { - network string - ip string - port int -} - -// Network is part of net.Addr interface -func (lc *NetAddr) Network() string { - return lc.network -} - -// String is part of net.Addr interface -func (lc *NetAddr) String() string { - return lc.ip -} - -// Port -func (lc *NetAddr) Port() int { - return lc.port -} - -// Host -func (lc *NetAddr) Host() string { - if lc.ip == Local { - return Local - } - return ConcatenatedKey(lc.ip, strconv.Itoa(lc.port)) -} diff --git a/utils/json_codec.go b/utils/json_codec.go deleted file mode 100644 index d8a149f9b..000000000 --- a/utils/json_codec.go +++ /dev/null @@ -1,60 +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 utils - -import ( - "encoding/json" - "io" -) - -func DecodeServerRequest(r io.Reader) (req *serverRequest, err error) { - req = new(serverRequest) - err = json.NewDecoder(r).Decode(req) - return -} - -// NewServerRequest used in dispatcherh tests -func NewServerRequest(method string, params, id json.RawMessage) *serverRequest { - return &serverRequest{ - Method: method, - Params: ¶ms, - Id: &id, - } -} - -type serverRequest struct { - Method string `json:"method"` - Params *json.RawMessage `json:"params"` - Id *json.RawMessage `json:"id"` -} - -func WriteServerResponse(w io.Writer, id *json.RawMessage, result, err interface{}) error { - return json.NewEncoder(w).Encode( - serverResponse{ - Id: id, - Result: result, - Error: err, - }) -} - -type serverResponse struct { - Id *json.RawMessage `json:"id"` - Result interface{} `json:"result"` - Error interface{} `json:"error"` -} diff --git a/utils/net.go b/utils/net.go new file mode 100644 index 000000000..304a3594b --- /dev/null +++ b/utils/net.go @@ -0,0 +1,143 @@ +/* +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 utils + +import ( + "encoding/json" + "fmt" + "io" + "net" + "net/http" + "strconv" + "strings" +) + +type Server interface { + RpcRegister(rcvr interface{}) + RpcRegisterName(name string, rcvr interface{}) + RegisterHttpFunc(pattern string, handler func(http.ResponseWriter, *http.Request)) + RegisterHttpHandler(pattern string, handler http.Handler) + BiRPCRegisterName(method string, handlerFunc interface{}) + BiRPCRegister(rcvr interface{}) +} + +func LocalAddr() *NetAddr { + return &NetAddr{network: Local, ip: Local} +} + +func NewNetAddr(network, host string) *NetAddr { + ip, port, err := net.SplitHostPort(host) + if err != nil { + Logger.Warning(fmt.Sprintf("failed parsing RemoteAddr: %s, err: %s", + host, err.Error())) + } + p, err := strconv.Atoi(port) + if err != nil { + Logger.Warning(fmt.Sprintf("failed converting port : %+v, err: %s", + port, err.Error())) + } + return &NetAddr{network: network, ip: ip, port: p} +} + +type NetAddr struct { + network string + ip string + port int +} + +// Network is part of net.Addr interface +func (lc *NetAddr) Network() string { + return lc.network +} + +// String is part of net.Addr interface +func (lc *NetAddr) String() string { + return lc.ip +} + +// Port . +func (lc *NetAddr) Port() int { + return lc.port +} + +// Host . +func (lc *NetAddr) Host() string { + if lc.ip == Local { + return Local + } + return ConcatenatedKey(lc.ip, strconv.Itoa(lc.port)) +} + +// GetRemoteIP returns the IP from http request +func GetRemoteIP(r *http.Request) (ip string, err error) { + ip = r.Header.Get("X-REAL-IP") + if net.ParseIP(ip) != nil { + return + } + for _, ip = range strings.Split(r.Header.Get("X-FORWARDED-FOR"), FIELDS_SEP) { + if net.ParseIP(ip) != nil { + return + } + } + if ip, _, err = net.SplitHostPort(r.RemoteAddr); err != nil { + return + } + if net.ParseIP(ip) != nil { + return + } + ip = EmptyString + err = fmt.Errorf("no valid ip found") + return +} + +func DecodeServerRequest(r io.Reader) (req *serverRequest, err error) { + req = new(serverRequest) + err = json.NewDecoder(r).Decode(req) + return +} + +// NewServerRequest used in dispatcherh tests +func NewServerRequest(method string, params, id json.RawMessage) *serverRequest { + return &serverRequest{ + Method: method, + Params: ¶ms, + Id: &id, + } +} + +type serverRequest struct { + Method string `json:"method"` + Params *json.RawMessage `json:"params"` + Id *json.RawMessage `json:"id"` +} + +func WriteServerResponse(w io.Writer, id *json.RawMessage, result, err interface{}) error { + return json.NewEncoder(w).Encode( + serverResponse{ + Id: id, + Result: result, + Error: err, + }) +} + +type serverResponse struct { + Id *json.RawMessage `json:"id"` + Result interface{} `json:"result"` + Error interface{} `json:"error"` +} diff --git a/utils/server_test.go b/utils/net_test.go similarity index 100% rename from utils/server_test.go rename to utils/net_test.go diff --git a/utils/rpc_params_test.go b/utils/rpc_params_test.go index 809afd5ea..1ad0b0d3c 100644 --- a/utils/rpc_params_test.go +++ b/utils/rpc_params_test.go @@ -1,3 +1,20 @@ +/* +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 utils import (