blob: 02df6ac2b49bb789801294eb4b1c7e1cfc5c285c [file] [log] [blame]
sslobodr392ebd52019-01-18 12:41:49 -05001/*
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// gRPC affinity router with active/active backends
17
18package afrouter
19
20import (
21 "fmt"
22 "errors"
23 "google.golang.org/grpc"
24 "github.com/opencord/voltha-go/common/log"
25)
26
27type RoundRobinRouter struct {
28 name string
29 routerType int // TODO: Likely not needed.
30 grpcService string
31 bkndClstr *backendCluster
32 curBknd **backend
33}
34
35func NewRoundRobinRouter(rconf *RouterConfig, config *RouteConfig) (Router, error) {
36 var err error = nil
37 var rtrn_err bool = false
38 // Validate the configuration
39
40 log.Debug("Creating a new round robin router")
41 // A name must exist
42 if config.Name == "" {
43 log.Error("A router 'name' must be specified")
44 rtrn_err = true
45 }
46
47 if rconf.ProtoPackage == "" {
48 log.Error("A 'package' must be specified")
49 rtrn_err = true
50 }
51
52 if rconf.ProtoService == "" {
53 log.Error("A 'service' must be specified")
54 rtrn_err = true
55 }
56
57 var bptr *backend
58 bptr = nil
59 rr := RoundRobinRouter{
60 name:config.Name,
61 grpcService:rconf.ProtoService,
62 curBknd:&bptr,
63 }
64
65 // This has already been validated bfore this function
66 // is called so just use it.
sslobodr5f0b5a32019-01-24 07:45:19 -050067 for idx := range rTypeNames {
sslobodr392ebd52019-01-18 12:41:49 -050068 if config.Type == rTypeNames[idx] {
69 rr.routerType = idx
70 break
71 }
72 }
73
74 // Create the backend cluster or link to an existing one
75 ok := true
76 if rr.bkndClstr, ok = bClusters[config.backendCluster.Name]; ok == false {
77 if rr.bkndClstr, err = NewBackendCluster(config.backendCluster); err != nil {
78 log.Errorf("Could not create a backend for router %s", config.Name)
79 rtrn_err = true
80 }
81 }
82
83 if rtrn_err {
84 return rr,errors.New(fmt.Sprintf("Failed to create a new router '%s'",rr.name))
85 }
86
87 return rr,nil
88}
89
90func (rr RoundRobinRouter) GetMetaKeyVal(serverStream grpc.ServerStream) (string,string,error) {
91 return "","",nil
92}
93
94func (rr RoundRobinRouter) BackendCluster(s string, mk string) (*backendCluster,error) {
95 return rr.bkndClstr, nil
96}
97
98func (rr RoundRobinRouter) Name() (string) {
99 return rr.name
100}
101
102func(rr RoundRobinRouter) Route(sel interface{}) (*backend) {
103 var err error
104 switch sl := sel.(type) {
105 case *nbFrame:
106 // Since this is a round robin router just get the next backend
107 if *rr.curBknd, err = rr.bkndClstr.nextBackend(*rr.curBknd,BE_SEQ_RR); err == nil {
108 return *rr.curBknd
109 } else {
110 sl.err = err
111 return nil
112 }
113 default:
114 log.Errorf("Internal: invalid data type in Route call %v", sel);
115 return nil
116 }
117 log.Errorf("Round robin error %v", err);
118 return nil
119}
120
121func (rr RoundRobinRouter) Service() (string) {
122 return rr.grpcService
123}
124
125func (rr RoundRobinRouter) FindBackendCluster(string) (*backendCluster) {
126 return rr.bkndClstr
127}
128
129func (rr RoundRobinRouter) ReplyHandler(sel interface{}) error { // This is a no-op
130 return nil
131}