[RICPLT-1832] - Rnib module changes + unit tests. After code review
[ric-plt/nodeb-rnib.git] / reader / rNibReader.go
1 //
2 // Copyright 2019 AT&T Intellectual Property
3 // Copyright 2019 Nokia
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //      http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16
17 package reader
18
19 import (
20         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/common"
21         "gerrit.o-ran-sc.org/r/ric-plt/nodeb-rnib.git/entities"
22         "gerrit.o-ran-sc.org/r/ric-plt/sdlgo"
23         "github.com/golang/protobuf/proto"
24         "github.com/pkg/errors"
25 )
26
27 var readerPool *common.Pool
28
29 type rNibReaderInstance struct {
30         sdl       *common.ISdlInstance
31         namespace string
32 }
33
34 /*
35 RNibReader interface allows retrieving data from redis BD by various keys
36 */
37 type RNibReader interface {
38         // GetNodeb retrieves responding nodeb entity from redis DB by nodeb inventory name
39         GetNodeb(inventoryName string) (*entities.NodebInfo, common.IRNibError)
40         // GetNodebByGlobalNbId retrieves responding nodeb entity from redis DB by nodeb global Id
41         GetNodebByGlobalNbId(nodeType entities.Node_Type, globalNbId *entities.GlobalNbId) (*entities.NodebInfo, common.IRNibError)
42         // GetCellList retrieves the list of cell entities belonging to responding nodeb entity from redis DB by nodeb inventory name
43         GetCellList(inventoryName string) (*entities.Cells, common.IRNibError)
44         // GetListGnbIds retrieves the list of gNodeb identity entities
45         GetListGnbIds() (*[]*entities.NbIdentity, common.IRNibError)
46         // GetListEnbIds retrieves the list of eNodeb identity entities
47         GetListEnbIds() (*[]*entities.NbIdentity, common.IRNibError)
48         // Close closes reader's pool
49         GetCountGnbList() (int, common.IRNibError)
50         // GetCell retrieves the cell entity belonging to responding nodeb from redis DB by nodeb inventory name and cell pci
51         GetCell(inventoryName string, pci uint32) (*entities.Cell, common.IRNibError)
52         // GetCellById retrieves the cell entity from redis DB by cell type and cell Id
53         GetCellById(cellType entities.Cell_Type, cellId string) (*entities.Cell, common.IRNibError)
54         // GetListNodebIds returns the full list of Nodeb identity entities
55         GetListNodebIds()([]*entities.NbIdentity, common.IRNibError)
56 }
57
58 const(
59         EnbType = "ENB"
60         GnbType = "GNB"
61 )
62
63 /*
64  Init initializes the infrastructure required for the RNibReader instance
65 */
66 func Init(namespace string, poolSize int) {
67         initPool(poolSize,
68                 func() interface{} {
69                         var sdlI common.ISdlInstance = sdlgo.NewSdlInstance(namespace, sdlgo.NewDatabase())
70                         return &rNibReaderInstance{sdl: &sdlI, namespace: namespace}
71                 },
72                 func(obj interface{}) {
73                         (*obj.(*rNibReaderInstance).sdl).Close()
74                 })
75 }
76
77 func initPool(poolSize int, newObj func() interface{}, destroyObj func(interface{})) {
78         readerPool = common.NewPool(poolSize, newObj, destroyObj)
79 }
80
81 /*
82 GetRNibReader returns RNibReader instance from the pool
83 */
84 func GetRNibReader() RNibReader {
85         return readerPool.Get().(RNibReader)
86 }
87
88 func (w *rNibReaderInstance) GetNodeb(inventoryName string) (*entities.NodebInfo, common.IRNibError) {
89         defer readerPool.Put(w)
90         key, rNibErr := common.ValidateAndBuildNodeBNameKey(inventoryName)
91         if rNibErr != nil {
92                 return nil, rNibErr
93         }
94         return w.getNodeb(key)
95 }
96
97 func (w *rNibReaderInstance) GetNodebByGlobalNbId(nodeType entities.Node_Type, globalNbId *entities.GlobalNbId) (*entities.NodebInfo, common.IRNibError) {
98         defer readerPool.Put(w)
99         key, rNibErr := common.ValidateAndBuildNodeBIdKey(nodeType.String(), globalNbId.GetPlmnId(), globalNbId.GetNbId())
100         if rNibErr != nil {
101                 return nil, rNibErr
102         }
103         return w.getNodeb(key)
104 }
105
106 func (w *rNibReaderInstance) GetCellList(inventoryName string) (*entities.Cells, common.IRNibError) {
107         cells := &entities.Cells{}
108         nb, err := w.GetNodeb(inventoryName)
109         if err != nil {
110                 return nil, err
111         }
112         if nb.GetEnb() != nil && len(nb.GetEnb().GetServedCells()) > 0 {
113                 cells.Type = entities.Cell_LTE_CELL
114                 cells.List = &entities.Cells_ServedCellInfos{ServedCellInfos: &entities.ServedCellInfoList{ServedCells: nb.GetEnb().GetServedCells()}}
115                 return cells, nil
116         } else if nb.GetGnb() != nil && len(nb.GetGnb().GetServedNrCells()) > 0 {
117                 cells.Type = entities.Cell_NR_CELL
118                 cells.List = &entities.Cells_ServedNrCells{ServedNrCells: &entities.ServedNRCellList{ServedCells: nb.GetGnb().GetServedNrCells()}}
119                 return cells, nil
120         }
121         return nil, common.NewResourceNotFoundError(errors.Errorf("#rNibReader.GetCellList - served cells not found. Responding node RAN name: %s.", inventoryName))
122 }
123
124 func (w *rNibReaderInstance) GetListGnbIds() (*[]*entities.NbIdentity, common.IRNibError) {
125         defer readerPool.Put(w)
126         return w.getListNodebIdsByType(GnbType)
127 }
128
129 func (w *rNibReaderInstance) GetListEnbIds() (*[]*entities.NbIdentity, common.IRNibError) {
130         defer readerPool.Put(w)
131         return w.getListNodebIdsByType(EnbType)
132 }
133
134 func (w *rNibReaderInstance) GetCountGnbList() (int, common.IRNibError) {
135         defer readerPool.Put(w)
136         size, err := (*w.sdl).GroupSize(GnbType)
137         if err != nil {
138                 return 0, common.NewInternalError(err)
139         }
140         return int(size), nil
141 }
142
143 func (w *rNibReaderInstance) GetCell(inventoryName string, pci uint32) (*entities.Cell, common.IRNibError) {
144         defer readerPool.Put(w)
145         key, rNibErr := common.ValidateAndBuildCellNamePciKey(inventoryName, pci)
146         if rNibErr != nil {
147                 return nil, rNibErr
148         }
149         return w.getCellByKey(key)
150 }
151
152 func (w *rNibReaderInstance) GetCellById(cellType entities.Cell_Type, cellId string) (*entities.Cell, common.IRNibError) {
153         defer readerPool.Put(w)
154         var key string
155         var rNibErr common.IRNibError
156         if cellType == entities.Cell_LTE_CELL {
157                 key, rNibErr = common.ValidateAndBuildCellIdKey(cellId)
158         } else if cellType == entities.Cell_NR_CELL {
159                 key, rNibErr = common.ValidateAndBuildNrCellIdKey(cellId)
160         } else {
161                 return nil, common.NewValidationError(errors.Errorf("#rNibReader.GetCellById - invalid cell type: %v", cellType))
162         }
163         if rNibErr != nil {
164                 return nil, rNibErr
165         }
166         return w.getCellByKey(key)
167 }
168
169 func (w *rNibReaderInstance) GetListNodebIds()([]*entities.NbIdentity, common.IRNibError){
170         defer readerPool.Put(w)
171         dataEnb, err := (*w.sdl).GetMembers(EnbType)
172         if err != nil{
173                 return nil, common.NewInternalError(err)
174         }
175         dataGnb, err := (*w.sdl).GetMembers(GnbType)
176         if err != nil{
177                 return nil, common.NewInternalError(err)
178         }
179         data, rnibErr := unmarshalIdentityList(append(dataEnb, dataGnb...))
180         return *data, rnibErr
181 }
182
183 func (w *rNibReaderInstance) getNodeb(key string) (*entities.NodebInfo, common.IRNibError) {
184         data, err := (*w.sdl).Get([]string{key})
185         if err != nil {
186                 return nil, common.NewInternalError(err)
187         }
188         nb := entities.NodebInfo{}
189         if data != nil && data[key] != nil {
190                 err = proto.Unmarshal([]byte(data[key].(string)), &nb)
191                 if err != nil {
192                         return nil, common.NewInternalError(err)
193                 }
194                 return &nb, nil
195         }
196         return nil, common.NewResourceNotFoundError(errors.Errorf("#rNibReader.getNodeb - responding node not found. Key: %s", key))
197 }
198
199 func (w *rNibReaderInstance) getCellByKey(key string) (*entities.Cell, common.IRNibError) {
200         data, err := (*w.sdl).Get([]string{key})
201         if err != nil {
202                 return nil, common.NewInternalError(err)
203         }
204         cell := entities.Cell{}
205         if data != nil && data[key] != nil {
206                 err = proto.Unmarshal([]byte(data[key].(string)), &cell)
207                 if err != nil {
208                         return nil, common.NewInternalError(err)
209                 }
210                 return &cell, nil
211         }
212         return nil, common.NewResourceNotFoundError(errors.Errorf("#rNibReader.getCellByKey - cell not found, key: %s", key))
213 }
214
215 func (w *rNibReaderInstance) getListNodebIdsByType(nbType string) (*[]*entities.NbIdentity, common.IRNibError) {
216         data, err := (*w.sdl).GetMembers(nbType)
217         if err != nil {
218                 return nil, common.NewInternalError(err)
219         }
220         return unmarshalIdentityList(data)
221 }
222
223 func unmarshalIdentityList(data []string) (*[]*entities.NbIdentity, common.IRNibError) {
224         var members []*entities.NbIdentity
225         for _, d := range data {
226                 member := entities.NbIdentity{}
227                 err := proto.Unmarshal([]byte(d), &member)
228                 if err != nil {
229                         return nil, common.NewInternalError(err)
230                 }
231                 members = append(members, &member)
232         }
233         return &members, nil
234 }
235
236 func Close() {
237         readerPool.Close()
238 }