blob: 8fe495a25714b8d1f4d3829beaf912ea6cbf9267 [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 (
Scott Bakere7144bc2019-10-01 14:16:47 -070020 "fmt"
21 "github.com/opencord/voltha-go/common/log"
22 "google.golang.org/grpc"
23)
24
25type RoundRobinRouter struct {
26 name string
27 grpcService string
28 cluster *cluster
29 currentBackend **backend
30}
31
32func newRoundRobinRouter(rconf *RouterConfig, config *RouteConfig) (Router, error) {
Scott Baker4989fe92019-10-09 17:03:06 -070033 var err error
Scott Bakere7144bc2019-10-01 14:16:47 -070034 var rtrn_err = false
35 // Validate the configuration
36
37 log.Debug("Creating a new round robin router")
38 // A name must exist
39 if config.Name == "" {
40 log.Error("A router 'name' must be specified")
41 rtrn_err = true
42 }
43
44 if rconf.ProtoPackage == "" {
45 log.Error("A 'package' must be specified")
46 rtrn_err = true
47 }
48
49 if rconf.ProtoService == "" {
50 log.Error("A 'service' must be specified")
51 rtrn_err = true
52 }
53
54 var bptr *backend
Scott Bakere7144bc2019-10-01 14:16:47 -070055 rr := RoundRobinRouter{
56 name: config.Name,
57 grpcService: rconf.ProtoService,
58 currentBackend: &bptr,
59 }
60
61 // Create the backend cluster or link to an existing one
Scott Baker4989fe92019-10-09 17:03:06 -070062 var ok bool
Scott Bakere7144bc2019-10-01 14:16:47 -070063 if rr.cluster, ok = clusters[config.backendCluster.Name]; !ok {
64 if rr.cluster, err = newBackendCluster(config.backendCluster); err != nil {
65 log.Errorf("Could not create a backend for router %s", config.Name)
66 rtrn_err = true
67 }
68 }
69
70 if rtrn_err {
Scott Baker4989fe92019-10-09 17:03:06 -070071 return rr, fmt.Errorf("Failed to create a new router '%s'", rr.name)
Scott Bakere7144bc2019-10-01 14:16:47 -070072 }
73
74 return rr, nil
75}
76
77func (rr RoundRobinRouter) GetMetaKeyVal(serverStream grpc.ServerStream) (string, string, error) {
78 return "", "", nil
79}
80
81func (rr RoundRobinRouter) IsStreaming(_ string) (bool, bool) {
82 panic("not implemented")
83}
84
85func (rr RoundRobinRouter) BackendCluster(s string, mk string) (*cluster, error) {
86 return rr.cluster, nil
87}
88
89func (rr RoundRobinRouter) Name() string {
90 return rr.name
91}
92
93func (rr RoundRobinRouter) Route(sel interface{}) (*backend, *connection) {
94 var err error
95 switch sl := sel.(type) {
96 case *requestFrame:
97 // Since this is a round robin router just get the next backend
98 if *rr.currentBackend, err = rr.cluster.nextBackend(*rr.currentBackend, BackendSequenceRoundRobin); err == nil {
99 return *rr.currentBackend, nil
100 } else {
101 sl.err = err
102 return nil, nil
103 }
104 default:
105 log.Errorf("Internal: invalid data type in Route call %v", sel)
106 return nil, nil
107 }
108}
109
110func (rr RoundRobinRouter) Service() string {
111 return rr.grpcService
112}
113
114func (rr RoundRobinRouter) FindBackendCluster(becName string) *cluster {
115 if becName == rr.cluster.name {
116 return rr.cluster
117 }
118 return nil
119}
120
121func (rr RoundRobinRouter) ReplyHandler(sel interface{}) error { // This is a no-op
122 return nil
123}