blob: 20bf3544eb196b1b7c15b22051f1c510cce7290a [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 "sync"
23 "google.golang.org/grpc"
24 "github.com/golang/protobuf/proto"
25 "github.com/opencord/voltha-go/common/log"
26)
27
28func Codec() grpc.Codec {
29 return CodecWithParent(&protoCodec{})
30}
31
32func CodecWithParent(fallback grpc.Codec) grpc.Codec {
33 return &rawCodec{fallback}
34}
35
36type rawCodec struct {
37 parentCodec grpc.Codec
38}
39
40type sbFrame struct {
41 payload []byte
42 router Router
43 method string
44 be *backend
45 lck sync.Mutex
46 metaKey string
47 metaVal string
48}
49
50type nbFrame struct {
51 payload []byte
52 router Router
53 be *backend
54 err error
55 mthdSlice []string
56 serNo chan uint64
57 metaKey string
58 metaVal string
59}
60
61func (c *rawCodec) Marshal(v interface{}) ([]byte, error) {
62 switch t := v.(type) {
63 case *sbFrame:
64 return t.payload, nil
65 case *nbFrame:
66 return t.payload, nil
67 default:
68 return c.parentCodec.Marshal(v)
69 }
70
71}
72
73func (c *rawCodec) Unmarshal(data []byte, v interface{}) error {
74 switch t := v.(type) {
75 case *sbFrame:
76 t.payload = data
77 // This is where the affinity is established on a northbound response
78 t.router.ReplyHandler(v)
79 return nil
80 case *nbFrame:
81 t.payload = data
82 // This is were the afinity value is pulled from the payload
83 // and the backend selected.
84 t.be = t.router.Route(v)
85 log.Debugf("Routing returned %v for method %s", t.be, t.mthdSlice[REQ_METHOD])
86 return nil
87 default:
88 return c.parentCodec.Unmarshal(data,v)
89 }
90}
91
92func (c *rawCodec) String() string {
93 return fmt.Sprintf("proxy>%s", c.parentCodec.String())
94}
95
96// protoCodec is a Codec implementation with protobuf. It is the default rawCodec for gRPC.
97type protoCodec struct{}
98
99func (protoCodec) Marshal(v interface{}) ([]byte, error) {
100 return proto.Marshal(v.(proto.Message))
101}
102
103func (protoCodec) Unmarshal(data []byte, v interface{}) error {
104 return proto.Unmarshal(data, v.(proto.Message))
105}
106
107func (protoCodec) String() string {
108 return "proto"
109}