blob: 2803141f3fb8a40c2683d234234071e928c21f31 [file] [log] [blame]
/*
* 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
}