| /* |
| * Copyright 2018-present Open Networking Foundation |
| |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package afrouter |
| |
| import ( |
| "fmt" |
| "github.com/opencord/voltha-lib-go/v2/pkg/log" |
| "google.golang.org/grpc" |
| ) |
| |
| type RoundRobinRouter struct { |
| name string |
| grpcService string |
| cluster *cluster |
| currentBackend **backend |
| } |
| |
| func newRoundRobinRouter(rconf *RouterConfig, config *RouteConfig) (Router, error) { |
| var err error |
| var rtrn_err = false |
| // Validate the configuration |
| |
| log.Debug("Creating a new round robin router") |
| // A name must exist |
| if config.Name == "" { |
| log.Error("A router 'name' must be specified") |
| rtrn_err = true |
| } |
| |
| if rconf.ProtoPackage == "" { |
| log.Error("A 'package' must be specified") |
| rtrn_err = true |
| } |
| |
| if rconf.ProtoService == "" { |
| log.Error("A 'service' must be specified") |
| rtrn_err = true |
| } |
| |
| var bptr *backend |
| rr := RoundRobinRouter{ |
| name: config.Name, |
| grpcService: rconf.ProtoService, |
| currentBackend: &bptr, |
| } |
| |
| // Create the backend cluster or link to an existing one |
| var ok bool |
| if rr.cluster, ok = clusters[config.backendCluster.Name]; !ok { |
| if rr.cluster, err = newBackendCluster(config.backendCluster); err != nil { |
| log.Errorf("Could not create a backend for router %s", config.Name) |
| rtrn_err = true |
| } |
| } |
| |
| if rtrn_err { |
| return rr, fmt.Errorf("Failed to create a new router '%s'", rr.name) |
| } |
| |
| return rr, nil |
| } |
| |
| func (rr RoundRobinRouter) GetMetaKeyVal(serverStream grpc.ServerStream) (string, string, error) { |
| return "", "", nil |
| } |
| |
| func (rr RoundRobinRouter) IsStreaming(_ string) (bool, bool) { |
| panic("not implemented") |
| } |
| |
| func (rr RoundRobinRouter) BackendCluster(s string, mk string) (*cluster, error) { |
| return rr.cluster, nil |
| } |
| |
| func (rr RoundRobinRouter) Name() string { |
| return rr.name |
| } |
| |
| func (rr RoundRobinRouter) Route(sel interface{}) (*backend, *connection) { |
| var err error |
| switch sl := sel.(type) { |
| case *requestFrame: |
| // Since this is a round robin router just get the next backend |
| if *rr.currentBackend, err = rr.cluster.nextBackend(*rr.currentBackend, BackendSequenceRoundRobin); err == nil { |
| return *rr.currentBackend, nil |
| } else { |
| sl.err = err |
| return nil, nil |
| } |
| default: |
| log.Errorf("Internal: invalid data type in Route call %v", sel) |
| return nil, nil |
| } |
| } |
| |
| func (rr RoundRobinRouter) Service() string { |
| return rr.grpcService |
| } |
| |
| func (rr RoundRobinRouter) FindBackendCluster(becName string) *cluster { |
| if becName == rr.cluster.name { |
| return rr.cluster |
| } |
| return nil |
| } |
| |
| func (rr RoundRobinRouter) ReplyHandler(sel interface{}) error { // This is a no-op |
| return nil |
| } |