blob: a9a130eda8b2c1b0348d00b0204aa429cacc6ec8 [file] [log] [blame]
Mohamed Abukar2e78e422019-06-02 11:45:52 +03001/*
2==================================================================================
3 Copyright (c) 2019 AT&T Intellectual Property.
4 Copyright (c) 2019 Nokia
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17==================================================================================
18*/
19
20package xapp
21
22import (
23 "fmt"
24 "github.com/spf13/viper"
25 "net/http"
Juha Hyttinen54066262020-09-16 10:37:28 +030026 "os"
27 "os/signal"
28 "sync/atomic"
29 "syscall"
30 "time"
Mohamed Abukar2e78e422019-06-02 11:45:52 +030031)
32
Mohamed Abukar192518d2019-06-11 18:06:50 +030033type ReadyCB func(interface{})
Juha Hyttinen54066262020-09-16 10:37:28 +030034type ShutdownCB func()
Mohamed Abukar349a0982019-06-08 18:15:42 +030035
Mohamed Abukar2e78e422019-06-02 11:45:52 +030036var (
37 // XApp is an application instance
Juha Hyttinenf49009a2019-11-26 10:28:14 +020038 Rmr *RMRClient
39 Sdl *SDLClient
40 Rnib *RNIBClient
41 Resource *Router
42 Metric *Metrics
43 Logger *Log
44 Config Configurator
Mohamed Abukar5120ec12020-02-04 11:01:24 +020045 Subscription *Subscriber
Mohamed Abukar8dcedb42020-03-10 13:20:56 +020046 Alarm *AlarmClient
Juha Hyttinenf49009a2019-11-26 10:28:14 +020047 readyCb ReadyCB
48 readyCbParams interface{}
Juha Hyttinen54066262020-09-16 10:37:28 +030049 shutdownCb ShutdownCB
50 shutdownFlag int32
51 shutdownCnt int32
Mohamed Abukar2e78e422019-06-02 11:45:52 +030052)
53
Mohamed Abukar775722c2019-06-10 16:41:57 +030054func IsReady() bool {
Juha Hyttinenf49009a2019-11-26 10:28:14 +020055 return Rmr != nil && Rmr.IsReady() && Sdl != nil && Sdl.IsReady()
Mohamed Abukar775722c2019-06-10 16:41:57 +030056}
57
Mohamed Abukar192518d2019-06-11 18:06:50 +030058func SetReadyCB(cb ReadyCB, params interface{}) {
Juha Hyttinenf49009a2019-11-26 10:28:14 +020059 readyCb = cb
60 readyCbParams = params
61}
62
Mohamed Abukarb8b191f2020-11-07 11:22:56 +020063func XappReadyCb(params interface{}) {
64 Alarm = NewAlarmClient(viper.GetString("moId"), viper.GetString("name"))
Juha Hyttinenf49009a2019-11-26 10:28:14 +020065 if readyCb != nil {
66 readyCb(readyCbParams)
67 }
Mohamed Abukar775722c2019-06-10 16:41:57 +030068}
69
Juha Hyttinen54066262020-09-16 10:37:28 +030070func SetShutdownCB(cb ShutdownCB) {
71 shutdownCb = cb
72}
73
Mohamed Abukarb8b191f2020-11-07 11:22:56 +020074func InstallSignalHandler() {
Juha Hyttinen54066262020-09-16 10:37:28 +030075 //
76 // Signal handlers to really exit program.
77 // shutdownCb can hang until application has
78 // made all needed gracefull shutdown actions
79 // hardcoded limit for shutdown is 20 seconds
80 //
81 interrupt := make(chan os.Signal, 1)
82 signal.Notify(interrupt, syscall.SIGINT, syscall.SIGTERM)
83 //signal handler function
84 go func() {
Mohamed Abukarb8b191f2020-11-07 11:22:56 +020085 for range interrupt {
Juha Hyttinen54066262020-09-16 10:37:28 +030086 if atomic.CompareAndSwapInt32(&shutdownFlag, 0, 1) {
87 // close function
88 go func() {
89 timeout := int(20)
90 sentry := make(chan struct{})
91 defer close(sentry)
92
93 // close callback
94 go func() {
95 if shutdownCb != nil {
96 shutdownCb()
97 }
98 sentry <- struct{}{}
99 }()
100 select {
101 case <-time.After(time.Duration(timeout) * time.Second):
102 Logger.Info("xapp-frame shutdown callback took more than %d seconds", timeout)
103 case <-sentry:
104 Logger.Info("xapp-frame shutdown callback handled within %d seconds", timeout)
105 }
106 os.Exit(0)
107 }()
108 } else {
109 newCnt := atomic.AddInt32(&shutdownCnt, 1)
110 Logger.Info("xapp-frame shutdown already ongoing. Forced exit counter %d/%d ", newCnt, 5)
111 if newCnt >= 5 {
112 Logger.Info("xapp-frame shutdown forced exit")
113 os.Exit(0)
114 }
115 continue
116 }
117
118 }
119 }()
Mohamed Abukar2e78e422019-06-02 11:45:52 +0300120}
121
Mohamed Abukarb8b191f2020-11-07 11:22:56 +0200122func init() {
123 // Load xapp configuration
124 Logger = LoadConfig()
125
Mohamed Abukar827a6412020-11-12 10:02:41 +0200126 if viper.IsSet("controls.logger.level") {
127 Logger.SetLevel(viper.GetInt("controls.logger.level"))
128 } else {
129 Logger.SetLevel(viper.GetInt("logger.level"))
130 }
Mohamed Abukarb8b191f2020-11-07 11:22:56 +0200131 Resource = NewRouter()
132 Config = Configurator{}
133 Metric = NewMetrics(viper.GetString("metrics.url"), viper.GetString("metrics.namespace"), Resource.router)
134 Subscription = NewSubscriber(viper.GetString("subscription.host"), viper.GetInt("subscription.timeout"))
Mohamed Abukar827a6412020-11-12 10:02:41 +0200135 Sdl = NewSDLClient(viper.GetString("controls.db.namespace"))
Mohamed Abukarb8b191f2020-11-07 11:22:56 +0200136 Rnib = NewRNIBClient()
137
138 InstallSignalHandler()
139}
140
Juha Hyttinenf49009a2019-11-26 10:28:14 +0200141func RunWithParams(c MessageConsumer, sdlcheck bool) {
142 Rmr = NewRMRClient()
Mohamed Abukarb8b191f2020-11-07 11:22:56 +0200143 Rmr.SetReadyCB(XappReadyCb, nil)
144
145 host := fmt.Sprintf(":%d", GetPortData("http").Port)
146 go http.ListenAndServe(host, Resource.router)
147 Logger.Info(fmt.Sprintf("Xapp started, listening on: %s", host))
Juha Hyttinenf49009a2019-11-26 10:28:14 +0200148 if sdlcheck {
149 Sdl.TestConnection()
150 }
Mohamed Abukar2e78e422019-06-02 11:45:52 +0300151 Rmr.Start(c)
152}
Juha Hyttinenf49009a2019-11-26 10:28:14 +0200153
154func Run(c MessageConsumer) {
155 RunWithParams(c, true)
156}