3131import io .grpc .Status ;
3232import io .grpc .xds .client .Bootstrapper ;
3333import io .grpc .xds .client .XdsTransportFactory ;
34- import java .util .Map ;
35- import java .util .concurrent .ConcurrentHashMap ;
3634import java .util .concurrent .TimeUnit ;
3735
38- /**
39- * A factory for creating gRPC-based transports for xDS communication.
40- *
41- * <p>WARNING: This class reuses channels when possible, based on the provided {@link
42- * Bootstrapper.ServerInfo} with important considerations. The {@link Bootstrapper.ServerInfo}
43- * includes {@link ChannelCredentials}, which is compared by reference equality. This means every
44- * {@link Bootstrapper.BootstrapInfo} would have non-equal copies of {@link
45- * Bootstrapper.ServerInfo}, even if they all represent the same xDS server configuration. For gRPC
46- * name resolution with the {@code xds} and {@code google-c2p} scheme, this transport sharing works
47- * as expected as it internally reuses a single {@link Bootstrapper.BootstrapInfo} instance.
48- * Otherwise, new transports would be created for each {@link Bootstrapper.ServerInfo} despite them
49- * possibly representing the same xDS server configuration and defeating the purpose of transport
50- * sharing.
51- */
5236final class GrpcXdsTransportFactory implements XdsTransportFactory {
5337
5438 private final CallCredentials callCredentials ;
55- // The map of xDS server info to its corresponding gRPC xDS transport.
56- // This enables reusing and sharing the same underlying gRPC channel.
57- //
58- // NOTE: ConcurrentHashMap is used as a per-entry lock and all reads and writes must be a mutation
59- // via the ConcurrentHashMap APIs to acquire the per-entry lock in order to ensure thread safety
60- // for reference counting of each GrpcXdsTransport instance.
61- private static final Map <Bootstrapper .ServerInfo , GrpcXdsTransport > xdsServerInfoToTransportMap =
62- new ConcurrentHashMap <>();
6339
6440 GrpcXdsTransportFactory (CallCredentials callCredentials ) {
6541 this .callCredentials = callCredentials ;
6642 }
6743
6844 @ Override
6945 public XdsTransport create (Bootstrapper .ServerInfo serverInfo ) {
70- return xdsServerInfoToTransportMap .compute (
71- serverInfo ,
72- (info , transport ) -> {
73- if (transport == null ) {
74- transport = new GrpcXdsTransport (serverInfo , callCredentials );
75- }
76- ++transport .refCount ;
77- return transport ;
78- });
46+ return new GrpcXdsTransport (serverInfo , callCredentials );
7947 }
8048
8149 @ VisibleForTesting
8250 public XdsTransport createForTest (ManagedChannel channel ) {
83- return new GrpcXdsTransport (channel , callCredentials , null );
51+ return new GrpcXdsTransport (channel , callCredentials );
8452 }
8553
8654 @ VisibleForTesting
8755 static class GrpcXdsTransport implements XdsTransport {
8856
8957 private final ManagedChannel channel ;
9058 private final CallCredentials callCredentials ;
91- private final Bootstrapper .ServerInfo serverInfo ;
92- // Must only be accessed via the ConcurrentHashMap APIs which act as the locking methods.
93- private int refCount = 0 ;
9459
9560 public GrpcXdsTransport (Bootstrapper .ServerInfo serverInfo ) {
9661 this (serverInfo , null );
9762 }
9863
9964 @ VisibleForTesting
10065 public GrpcXdsTransport (ManagedChannel channel ) {
101- this (channel , null , null );
66+ this (channel , null );
10267 }
10368
10469 public GrpcXdsTransport (Bootstrapper .ServerInfo serverInfo , CallCredentials callCredentials ) {
@@ -108,17 +73,12 @@ public GrpcXdsTransport(Bootstrapper.ServerInfo serverInfo, CallCredentials call
10873 .keepAliveTime (5 , TimeUnit .MINUTES )
10974 .build ();
11075 this .callCredentials = callCredentials ;
111- this .serverInfo = serverInfo ;
11276 }
11377
11478 @ VisibleForTesting
115- public GrpcXdsTransport (
116- ManagedChannel channel ,
117- CallCredentials callCredentials ,
118- Bootstrapper .ServerInfo serverInfo ) {
79+ public GrpcXdsTransport (ManagedChannel channel , CallCredentials callCredentials ) {
11980 this .channel = checkNotNull (channel , "channel" );
12081 this .callCredentials = callCredentials ;
121- this .serverInfo = serverInfo ;
12282 }
12383
12484 @ Override
@@ -138,19 +98,7 @@ public <ReqT, RespT> StreamingCall<ReqT, RespT> createStreamingCall(
13898
13999 @ Override
140100 public void shutdown () {
141- if (serverInfo == null ) {
142- channel .shutdown ();
143- return ;
144- }
145- xdsServerInfoToTransportMap .computeIfPresent (
146- serverInfo ,
147- (info , transport ) -> {
148- if (--transport .refCount == 0 ) { // Prefix decrement and return the updated value.
149- transport .channel .shutdown ();
150- return null ; // Remove mapping.
151- }
152- return transport ;
153- });
101+ channel .shutdown ();
154102 }
155103
156104 private class XdsStreamingCall <ReqT , RespT > implements
0 commit comments