blob: b5f031e69264cca9e261e455dc99bff35586e0d0 [file] [log] [blame]
Scott Bakere7144bc2019-10-01 14:16:47 -07001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package afrouter
18
19import (
20 "errors"
21 "fmt"
22 "github.com/opencord/voltha-go/common/log"
23 "google.golang.org/grpc"
24)
25
26type RoundRobinRouter struct {
27 name string
28 grpcService string
29 cluster *cluster
30 currentBackend **backend
31}
32
33func newRoundRobinRouter(rconf *RouterConfig, config *RouteConfig) (Router, error) {
34 var err error = nil
35 var rtrn_err = false
36 // Validate the configuration
37
38 log.Debug("Creating a new round robin router")
39 // A name must exist
40 if config.Name == "" {
41 log.Error("A router 'name' must be specified")
42 rtrn_err = true
43 }
44
45 if rconf.ProtoPackage == "" {
46 log.Error("A 'package' must be specified")
47 rtrn_err = true
48 }
49
50 if rconf.ProtoService == "" {
51 log.Error("A 'service' must be specified")
52 rtrn_err = true
53 }
54
55 var bptr *backend
56 bptr = nil
57 rr := RoundRobinRouter{
58 name: config.Name,
59 grpcService: rconf.ProtoService,
60 currentBackend: &bptr,
61 }
62
63 // Create the backend cluster or link to an existing one
64 ok := true
65 if rr.cluster, ok = clusters[config.backendCluster.Name]; !ok {
66 if rr.cluster, err = newBackendCluster(config.backendCluster); err != nil {
67 log.Errorf("Could not create a backend for router %s", config.Name)
68 rtrn_err = true
69 }
70 }
71
72 if rtrn_err {
73 return rr, errors.New(fmt.Sprintf("Failed to create a new router '%s'", rr.name))
74 }
75
76 return rr, nil
77}
78
79func (rr RoundRobinRouter) GetMetaKeyVal(serverStream grpc.ServerStream) (string, string, error) {
80 return "", "", nil
81}
82
83func (rr RoundRobinRouter) IsStreaming(_ string) (bool, bool) {
84 panic("not implemented")
85}
86
87func (rr RoundRobinRouter) BackendCluster(s string, mk string) (*cluster, error) {
88 return rr.cluster, nil
89}
90
91func (rr RoundRobinRouter) Name() string {
92 return rr.name
93}
94
95func (rr RoundRobinRouter) Route(sel interface{}) (*backend, *connection) {
96 var err error
97 switch sl := sel.(type) {
98 case *requestFrame:
99 // Since this is a round robin router just get the next backend
100 if *rr.currentBackend, err = rr.cluster.nextBackend(*rr.currentBackend, BackendSequenceRoundRobin); err == nil {
101 return *rr.currentBackend, nil
102 } else {
103 sl.err = err
104 return nil, nil
105 }
106 default:
107 log.Errorf("Internal: invalid data type in Route call %v", sel)
108 return nil, nil
109 }
110}
111
112func (rr RoundRobinRouter) Service() string {
113 return rr.grpcService
114}
115
116func (rr RoundRobinRouter) FindBackendCluster(becName string) *cluster {
117 if becName == rr.cluster.name {
118 return rr.cluster
119 }
120 return nil
121}
122
123func (rr RoundRobinRouter) ReplyHandler(sel interface{}) error { // This is a no-op
124 return nil
125}