@@ -51,6 +51,7 @@ import (
51
51
"google.golang.org/grpc/encoding"
52
52
"google.golang.org/grpc/metadata"
53
53
"google.golang.org/grpc/stats"
54
+ "storj.io/drpc"
54
55
)
55
56
56
57
// NewServer sets up an RPC server. Depending on the ServerOptions, the Server
@@ -226,7 +227,10 @@ type Context struct {
226
227
227
228
localInternalClient RestrictedInternalClient
228
229
230
+ // peers is a map of gRPC connections to other nodes.
229
231
peers peerMap [* grpc.ClientConn ]
232
+ // drpcPeers is a map of DRPC connections to other nodes.
233
+ drpcPeers peerMap [drpc.Conn ]
230
234
231
235
// dialbackMap is a map of currently executing dialback connections. This map
232
236
// is typically empty or close to empty. It only holds entries that are being
@@ -1998,6 +2002,16 @@ func (rpcCtx *Context) GRPCUnvalidatedDial(
1998
2002
return rpcCtx .grpcDialNodeInternal (target , 0 , locality , rpcbase .SystemClass )
1999
2003
}
2000
2004
2005
+ // DRPCUnvalidatedDial uses DRPCDialNode and disables validation of the
2006
+ // node ID between client and server. This function should only be
2007
+ // used with the gossip client and CLI commands which can talk to any
2008
+ // node. This method implies a SystemClass.
2009
+ func (rpcCtx * Context ) DRPCUnvalidatedDial (
2010
+ target string , locality roachpb.Locality ,
2011
+ ) * DRPCConnection {
2012
+ return rpcCtx .drpcDialNodeInternal (target , 0 , locality , rpcbase .SystemClass )
2013
+ }
2014
+
2001
2015
// GRPCDialNode calls grpc.Dial with options appropriate for the
2002
2016
// context and class (see the comment on ConnectionClass).
2003
2017
//
@@ -2019,6 +2033,27 @@ func (rpcCtx *Context) GRPCDialNode(
2019
2033
return rpcCtx .grpcDialNodeInternal (target , remoteNodeID , remoteLocality , class )
2020
2034
}
2021
2035
2036
+ // DRPCDialNode dials a DRPC connection with options appropriate for the
2037
+ // context and class (see the comment on ConnectionClass).
2038
+ //
2039
+ // The remoteNodeID becomes a constraint on the expected node ID of
2040
+ // the remote node; this is checked during heartbeats. The caller is
2041
+ // responsible for ensuring the remote node ID is known prior to using
2042
+ // this function.
2043
+ func (rpcCtx * Context ) DRPCDialNode (
2044
+ target string ,
2045
+ remoteNodeID roachpb.NodeID ,
2046
+ remoteLocality roachpb.Locality ,
2047
+ class rpcbase.ConnectionClass ,
2048
+ ) * DRPCConnection {
2049
+ if remoteNodeID == 0 && ! rpcCtx .TestingAllowNamedRPCToAnonymousServer {
2050
+ log .Fatalf (
2051
+ rpcCtx .makeDialCtx (target , remoteNodeID , class ),
2052
+ "%v" , errors .AssertionFailedf ("invalid node ID 0 in DRPCDialNode()" ))
2053
+ }
2054
+ return rpcCtx .drpcDialNodeInternal (target , remoteNodeID , remoteLocality , class )
2055
+ }
2056
+
2022
2057
// GRPCDialPod wraps GRPCDialNode and treats the `remoteInstanceID`
2023
2058
// argument as a `NodeID` which it converts. This works because the
2024
2059
// tenant gRPC server is initialized using the `InstanceID` so it
@@ -2035,6 +2070,22 @@ func (rpcCtx *Context) GRPCDialPod(
2035
2070
return rpcCtx .GRPCDialNode (target , roachpb .NodeID (remoteInstanceID ), remoteLocality , class )
2036
2071
}
2037
2072
2073
+ // DRPCDialPod wraps DRPCDialNode and treats the `remoteInstanceID`
2074
+ // argument as a `NodeID` which it converts. This works because the
2075
+ // tenant DRPC server is initialized using the `InstanceID` so it
2076
+ // accepts our connection as matching the ID we're dialing.
2077
+ //
2078
+ // Since DRPCDialNode accepts a separate `target` and `NodeID` it
2079
+ // requires no further modification to work between pods.
2080
+ func (rpcCtx * Context ) DRPCDialPod (
2081
+ target string ,
2082
+ remoteInstanceID base.SQLInstanceID ,
2083
+ remoteLocality roachpb.Locality ,
2084
+ class rpcbase.ConnectionClass ,
2085
+ ) * DRPCConnection {
2086
+ return rpcCtx .DRPCDialNode (target , roachpb .NodeID (remoteInstanceID ), remoteLocality , class )
2087
+ }
2088
+
2038
2089
// grpcDialNodeInternal connects to the remote node and sets up the async heartbeater.
2039
2090
// This intentionally takes no `context.Context`; it uses one derived from rpcCtx.masterCtx.
2040
2091
func (rpcCtx * Context ) grpcDialNodeInternal (
@@ -2050,8 +2101,37 @@ func (rpcCtx *Context) grpcDialNodeInternal(
2050
2101
}
2051
2102
2052
2103
// Slow path. Race to create a peer.
2053
- conns := & rpcCtx .peers
2104
+ return rpcDialNodeInternal (
2105
+ rpcCtx , k , newGRPCPeerOptions (rpcCtx , k , remoteLocality ),
2106
+ )
2107
+ }
2108
+
2109
+ // drpcDialNodeInternal connects to the remote node and sets up the async heartbeater.
2110
+ // This intentionally takes no `context.Context`; it uses one derived from rpcCtx.masterCtx.
2111
+ func (rpcCtx * Context ) drpcDialNodeInternal (
2112
+ target string ,
2113
+ remoteNodeID roachpb.NodeID ,
2114
+ remoteLocality roachpb.Locality ,
2115
+ class rpcbase.ConnectionClass ,
2116
+ ) * DRPCConnection {
2117
+ k := peerKey {TargetAddr : target , NodeID : remoteNodeID , Class : class }
2118
+ if p , ok := rpcCtx .drpcPeers .get (k ); ok {
2119
+ // There's a cached peer, so we have a cached connection, use it.
2120
+ return p .c
2121
+ }
2122
+
2123
+ // Slow path. Race to create a peer.
2124
+ return rpcDialNodeInternal (
2125
+ rpcCtx , k , newDRPCPeerOptions (rpcCtx , k , remoteLocality ),
2126
+ )
2127
+ }
2054
2128
2129
+ // rpcDialNodeInternal is used to dial a new connection to the peer if one
2130
+ // doesn't already exist.
2131
+ func rpcDialNodeInternal [Conn rpcConn ](
2132
+ rpcCtx * Context , k peerKey , peerOpts * peerOptions [Conn ],
2133
+ ) * Connection [Conn ] {
2134
+ conns := peerOpts .peers
2055
2135
conns .mu .Lock ()
2056
2136
defer conns .mu .Unlock ()
2057
2137
@@ -2060,12 +2140,11 @@ func (rpcCtx *Context) grpcDialNodeInternal(
2060
2140
}
2061
2141
2062
2142
// Won race. Actually create a peer.
2063
-
2064
2143
if conns .mu .m == nil {
2065
- conns .mu .m = map [peerKey ]* peer [* grpc. ClientConn ]{}
2144
+ conns .mu .m = map [peerKey ]* peer [Conn ]{}
2066
2145
}
2067
2146
2068
- p := newPeer (rpcCtx , k , newGRPCPeerOptions ( rpcCtx , k , remoteLocality ) )
2147
+ p := newPeer (rpcCtx , k , peerOpts )
2069
2148
// (Asynchronously) Start the probe (= heartbeat loop). The breaker is healthy
2070
2149
// right now (it was just created) but the call to `.Probe` will launch the
2071
2150
// probe[1] regardless.
0 commit comments