2 ==================================================================================
3 Copyright (c) 2019 AT&T Intellectual Property.
4 Copyright (c) 2019 Nokia
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
10 http://www.apache.org/licenses/LICENSE-2.0
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 ==================================================================================
28 #include <rmr/RIC_message_types.h>
30 void write_bytes_array(unsigned char *dst, void *data, int len) {
31 memcpy((void *)dst, (void *)data, len);
35 #cgo LDFLAGS: -lrmr_nng -lnng
40 "github.com/spf13/viper"
47 var RMRCounterOpts = []CounterOpts{
48 {Name: "Transmitted", Help: "The total number of transmited RMR messages"},
49 {Name: "Received", Help: "The total number of received RMR messages"},
50 {Name: "TransmitError", Help: "The total number of RMR transmission errors"},
51 {Name: "ReceiveError", Help: "The total number of RMR receive errors"},
55 type RMRStatistics struct{}
57 type RMRClient struct {
58 context unsafe.Pointer
62 stat map[string]Counter
63 consumers []MessageConsumer
65 readyCbParams interface{}
68 type MessageConsumer interface {
69 Consume(mtype int, sid int, len int, payload []byte) error
72 func NewRMRClient() *RMRClient {
73 p := C.CString(viper.GetString("rmr.protPort"))
74 m := C.int(viper.GetInt("rmr.maxSize"))
75 defer C.free(unsafe.Pointer(p))
77 ctx := C.rmr_init(p, m, C.int(0))
79 Logger.Error("rmrClient: Initializing RMR context failed, bailing out!")
84 consumers: make([]MessageConsumer, 0),
85 stat: Metric.RegisterCounterGroup(RMRCounterOpts, "RMR"),
89 func (m *RMRClient) Start(c MessageConsumer) {
91 Logger.Info("rmrClient: Waiting for RMR to be ready ...")
93 if m.ready = int(C.rmr_ready(m.context)); m.ready == 1 {
96 time.Sleep(10 * time.Second)
98 m.wg.Add(viper.GetInt("rmr.numWorkers"))
101 m.consumers = append(m.consumers, c)
104 for w := 0; w < viper.GetInt("rmr.numWorkers"); w++ {
105 go m.Worker("worker-"+strconv.Itoa(w), 0)
108 if m.readyCb != nil {
109 m.readyCb(m.readyCbParams)
115 func (m *RMRClient) Worker(taskName string, msgSize int) {
116 p := viper.GetString("rmr.protPort")
117 Logger.Info("rmrClient: '%s': receiving messages on [%s]", taskName, p)
121 rxBuffer := C.rmr_rcv_msg(m.context, nil)
123 m.UpdateStatCounter("ReceiveError")
126 m.UpdateStatCounter("Received")
128 go m.parseMessage(rxBuffer)
132 func (m *RMRClient) parseMessage(rxBuffer *C.rmr_mbuf_t) {
133 if len(m.consumers) == 0 {
134 Logger.Info("rmrClient: No message handlers defined, message discarded!")
138 for _, c := range m.consumers {
139 cptr := unsafe.Pointer(rxBuffer.payload)
140 payload := C.GoBytes(cptr, C.int(rxBuffer.len))
142 err := c.Consume(int(rxBuffer.mtype), int(rxBuffer.sub_id), int(rxBuffer.len), payload)
144 Logger.Warn("rmrClient: Consumer returned error: %v", err)
149 func (m *RMRClient) Allocate() *C.rmr_mbuf_t {
150 buf := C.rmr_alloc_msg(m.context, 0)
152 Logger.Error("rmrClient: Allocating message buffer failed!")
158 func (m *RMRClient) Send(mtype int, sid int, len int, payload []byte) bool {
161 buf.mtype = C.int(mtype)
162 buf.sub_id = C.int(sid)
164 datap := C.CBytes(payload)
167 C.write_bytes_array(buf.payload, datap, C.int(len))
169 return m.SendBuf(buf)
172 func (m *RMRClient) SendBuf(txBuffer *C.rmr_mbuf_t) bool {
173 for i := 0; i < 10; i++ {
175 txBuffer := C.rmr_send_msg(m.context, txBuffer)
178 } else if txBuffer.state != C.RMR_OK {
179 if txBuffer.state != C.RMR_ERR_RETRY {
180 time.Sleep(100 * time.Microsecond)
181 m.UpdateStatCounter("TransmitError")
183 for j := 0; j < 100 && txBuffer.state == C.RMR_ERR_RETRY; j++ {
184 txBuffer = C.rmr_send_msg(m.context, txBuffer)
188 if txBuffer.state == C.RMR_OK {
189 m.UpdateStatCounter("Transmitted")
193 m.UpdateStatCounter("TransmitError")
197 func (m *RMRClient) UpdateStatCounter(name string) {
203 func (m *RMRClient) RegisterMetrics() {
204 m.stat = Metric.RegisterCounterGroup(RMRCounterOpts, "RMR")
208 func (m *RMRClient) GetStat() (r RMRStatistics) {
212 func (m *RMRClient) Wait() {
216 func (m *RMRClient) IsReady() bool {
220 func (m *RMRClient) SetReadyCB(cb ReadyCB, params interface{}) {
222 m.readyCbParams = params
225 func (m *RMRClient) GetRicMessageId(name string) (int, bool) {
226 id, ok := RICMessageTypes[name]
230 func (m *RMRClient) GetRicMessageName(id int) (s string) {
231 for k, v := range RICMessageTypes {