X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=pkg%2Fxapp%2Fxapp.go;h=a9a130eda8b2c1b0348d00b0204aa429cacc6ec8;hb=refs%2Fchanges%2F51%2F5051%2F1;hp=c51e0ac5bee305ca8f76bae1e7473300961a235b;hpb=775722c877ef7110cdb4e992f5c216e0e03775c4;p=ric-plt%2Fxapp-frame.git diff --git a/pkg/xapp/xapp.go b/pkg/xapp/xapp.go index c51e0ac..a9a130e 100755 --- a/pkg/xapp/xapp.go +++ b/pkg/xapp/xapp.go @@ -23,57 +23,134 @@ import ( "fmt" "github.com/spf13/viper" "net/http" + "os" + "os/signal" + "sync/atomic" + "syscall" + "time" ) -type ReadyCB func() +type ReadyCB func(interface{}) +type ShutdownCB func() var ( // XApp is an application instance - Rmr *RMRClient - Sdl *SDLClient - Rnib *RNIBClient - Resource *Router - Metric *Metrics - Logger *Log - Config Configurator + Rmr *RMRClient + Sdl *SDLClient + Rnib *RNIBClient + Resource *Router + Metric *Metrics + Logger *Log + Config Configurator + Subscription *Subscriber + Alarm *AlarmClient + readyCb ReadyCB + readyCbParams interface{} + shutdownCb ShutdownCB + shutdownFlag int32 + shutdownCnt int32 ) func IsReady() bool { - return Rmr.IsReady() && Sdl.IsReady() + return Rmr != nil && Rmr.IsReady() && Sdl != nil && Sdl.IsReady() } -func SetReadyCB(cb ReadyCB) { - Rmr.SetReadyCB(cb) +func SetReadyCB(cb ReadyCB, params interface{}) { + readyCb = cb + readyCbParams = params +} + +func XappReadyCb(params interface{}) { + Alarm = NewAlarmClient(viper.GetString("moId"), viper.GetString("name")) + if readyCb != nil { + readyCb(readyCbParams) + } +} + +func SetShutdownCB(cb ShutdownCB) { + shutdownCb = cb +} + +func InstallSignalHandler() { + // + // Signal handlers to really exit program. + // shutdownCb can hang until application has + // made all needed gracefull shutdown actions + // hardcoded limit for shutdown is 20 seconds + // + interrupt := make(chan os.Signal, 1) + signal.Notify(interrupt, syscall.SIGINT, syscall.SIGTERM) + //signal handler function + go func() { + for range interrupt { + if atomic.CompareAndSwapInt32(&shutdownFlag, 0, 1) { + // close function + go func() { + timeout := int(20) + sentry := make(chan struct{}) + defer close(sentry) + + // close callback + go func() { + if shutdownCb != nil { + shutdownCb() + } + sentry <- struct{}{} + }() + select { + case <-time.After(time.Duration(timeout) * time.Second): + Logger.Info("xapp-frame shutdown callback took more than %d seconds", timeout) + case <-sentry: + Logger.Info("xapp-frame shutdown callback handled within %d seconds", timeout) + } + os.Exit(0) + }() + } else { + newCnt := atomic.AddInt32(&shutdownCnt, 1) + Logger.Info("xapp-frame shutdown already ongoing. Forced exit counter %d/%d ", newCnt, 5) + if newCnt >= 5 { + Logger.Info("xapp-frame shutdown forced exit") + os.Exit(0) + } + continue + } + + } + }() } func init() { // Load xapp configuration Logger = LoadConfig() - Logger.SetLevel(viper.GetInt("logger.level")) + if viper.IsSet("controls.logger.level") { + Logger.SetLevel(viper.GetInt("controls.logger.level")) + } else { + Logger.SetLevel(viper.GetInt("logger.level")) + } Resource = NewRouter() Config = Configurator{} Metric = NewMetrics(viper.GetString("metrics.url"), viper.GetString("metrics.namespace"), Resource.router) + Subscription = NewSubscriber(viper.GetString("subscription.host"), viper.GetInt("subscription.timeout")) + Sdl = NewSDLClient(viper.GetString("controls.db.namespace")) + Rnib = NewRNIBClient() + + InstallSignalHandler() +} + +func RunWithParams(c MessageConsumer, sdlcheck bool) { Rmr = NewRMRClient() + Rmr.SetReadyCB(XappReadyCb, nil) - if viper.IsSet("db.namespaces") { - namespaces := viper.GetStringSlice("db.namespaces") - if namespaces[0] != "" { - Sdl = NewSDLClient(viper.GetStringSlice("db.namespaces")[0]) - } - if namespaces[1] != "" { - Rnib = NewRNIBClient(viper.GetStringSlice("db.namespaces")[1]) - } - } else { - Sdl = NewSDLClient(viper.GetString("db.namespace")) + host := fmt.Sprintf(":%d", GetPortData("http").Port) + go http.ListenAndServe(host, Resource.router) + Logger.Info(fmt.Sprintf("Xapp started, listening on: %s", host)) + if sdlcheck { + Sdl.TestConnection() } + Rmr.Start(c) } func Run(c MessageConsumer) { - go http.ListenAndServe(viper.GetString("local.host"), Resource.router) - - Logger.Info(fmt.Sprintf("Xapp started, listening on: %s", viper.GetString("local.host"))) - - Sdl.TestConnection() - Rmr.Start(c) + RunWithParams(c, true) }