blob: 5b44b599c4efecc8a07e296e7d6779b597673b53 [file] [log] [blame]
lryan56e307f2014-12-05 13:25:08 -08001/*
2 * Copyright 2014, Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
nmittlerb687bdc2015-08-31 16:13:39 -070032package io.grpc.internal;
zhangkun8d6d12e2014-10-15 13:04:19 -070033
Carl Mastrangelo82a79d82015-12-07 14:40:11 -080034import static com.google.common.base.MoreObjects.firstNonNull;
Kun Zhang527fd672016-06-17 09:47:41 -070035import static com.google.common.base.Preconditions.checkArgument;
Carl Mastrangelo82a79d82015-12-07 14:40:11 -080036
Kun Zhang132f7a92016-10-06 17:15:24 -070037import com.google.census.Census;
38import com.google.census.CensusContextFactory;
Kun Zhang631a9d52016-06-02 16:47:36 -070039import com.google.common.annotations.VisibleForTesting;
Kun Zhang942f4c92015-09-04 17:21:44 -070040import com.google.common.base.Preconditions;
buchgr602473d2015-11-11 12:53:08 +010041import com.google.common.util.concurrent.MoreExecutors;
zhangkun8d6d12e2014-10-15 13:04:19 -070042
Kun Zhang942f4c92015-09-04 17:21:44 -070043import io.grpc.Attributes;
44import io.grpc.ClientInterceptor;
Carl Mastrangelo82a79d82015-12-07 14:40:11 -080045import io.grpc.CompressorRegistry;
46import io.grpc.DecompressorRegistry;
Kun Zhang132f7a92016-10-06 17:15:24 -070047import io.grpc.Internal;
Kun Zhang942f4c92015-09-04 17:21:44 -070048import io.grpc.LoadBalancer;
49import io.grpc.ManagedChannelBuilder;
50import io.grpc.NameResolver;
Eric Anderson56a29382016-06-11 11:55:49 -070051import io.grpc.NameResolverProvider;
Lukasz Strzalkowski577164c2016-08-23 00:40:09 +020052import io.grpc.PickFirstBalancerFactory;
Kun Zhang942f4c92015-09-04 17:21:44 -070053import io.grpc.ResolvedServerInfo;
Lukasz Strzalkowski23652c52016-08-19 16:56:56 +020054import io.grpc.ResolvedServerInfoGroup;
Kun Zhang942f4c92015-09-04 17:21:44 -070055
56import java.net.SocketAddress;
57import java.net.URI;
Kun Zhang631a9d52016-06-02 16:47:36 -070058import java.net.URISyntaxException;
Eric Anderson0df3d5e2015-06-25 18:00:00 -070059import java.util.ArrayList;
60import java.util.Arrays;
Kun Zhang942f4c92015-09-04 17:21:44 -070061import java.util.Collections;
Eric Anderson0df3d5e2015-06-25 18:00:00 -070062import java.util.List;
Louis Ryan6a782a02015-09-03 14:27:48 -070063import java.util.concurrent.Executor;
zhangkun8d6d12e2014-10-15 13:04:19 -070064
Kun Zhang527fd672016-06-17 09:47:41 -070065import java.util.concurrent.TimeUnit;
zhangkun8d6d12e2014-10-15 13:04:19 -070066import javax.annotation.Nullable;
67
68/**
69 * The base class for channel builders.
nathanmittler0304b3d2014-10-24 13:39:13 -070070 *
nmittlerb687bdc2015-08-31 16:13:39 -070071 * @param <T> The concrete type of this builder.
zhangkun8d6d12e2014-10-15 13:04:19 -070072 */
nmittlerb687bdc2015-08-31 16:13:39 -070073public abstract class AbstractManagedChannelImplBuilder
74 <T extends AbstractManagedChannelImplBuilder<T>> extends ManagedChannelBuilder<T> {
Kun Zhang16247152015-12-08 17:52:05 -080075 private static final String DIRECT_ADDRESS_SCHEME = "directaddress";
Eric Andersonaeeebb72014-12-19 16:41:03 -080076
Kun Zhang527fd672016-06-17 09:47:41 -070077 /**
78 * An idle timeout larger than this would disable idle mode.
79 */
80 @VisibleForTesting
81 static final long IDLE_MODE_MAX_TIMEOUT_DAYS = 30;
82
83 /**
Kun Zhangd74091f2016-09-16 22:34:27 -070084 * The default idle timeout.
85 */
86 @VisibleForTesting
87 static final long IDLE_MODE_DEFAULT_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(30);
88
89 /**
Kun Zhang527fd672016-06-17 09:47:41 -070090 * An idle timeout smaller than this would be capped to it.
91 */
92 @VisibleForTesting
93 static final long IDLE_MODE_MIN_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(1);
94
ejona7235a392015-01-13 13:38:54 -080095 @Nullable
Louis Ryan6a782a02015-09-03 14:27:48 -070096 private Executor executor;
Eric Anderson0df3d5e2015-06-25 18:00:00 -070097 private final List<ClientInterceptor> interceptors = new ArrayList<ClientInterceptor>();
zhangkun8d6d12e2014-10-15 13:04:19 -070098
Kun Zhangefac6792015-10-22 14:59:44 -070099 private final String target;
Kun Zhang942f4c92015-09-04 17:21:44 -0700100
101 @Nullable
102 private final SocketAddress directServerAddress;
103
nmittler8c1d38a2015-06-01 08:31:00 -0700104 @Nullable
105 private String userAgent;
106
Kun Zhang942f4c92015-09-04 17:21:44 -0700107 @Nullable
108 private String authorityOverride;
109
110 @Nullable
111 private NameResolver.Factory nameResolverFactory;
112
113 @Nullable
114 private LoadBalancer.Factory loadBalancerFactory;
115
Carl Mastrangelo82a79d82015-12-07 14:40:11 -0800116 @Nullable
117 private DecompressorRegistry decompressorRegistry;
118
119 @Nullable
120 private CompressorRegistry compressorRegistry;
121
Kun Zhangd74091f2016-09-16 22:34:27 -0700122 private long idleTimeoutMillis = IDLE_MODE_DEFAULT_TIMEOUT_MILLIS;
Kun Zhang527fd672016-06-17 09:47:41 -0700123
Carl Mastrangelofdd062c2016-10-26 16:55:41 -0700124 private int maxInboundMessageSize = GrpcUtil.DEFAULT_MAX_MESSAGE_SIZE;
125
126 // Can be overriden by subclasses.
127 @Override
128 public T maxInboundMessageSize(int max) {
129 checkArgument(max >= 0, "negative max");
130 maxInboundMessageSize = max;
131 return thisT();
132 }
133
134 protected final int maxInboundMessageSize() {
135 return maxInboundMessageSize;
136 }
137
Kun Zhang132f7a92016-10-06 17:15:24 -0700138 @Nullable
139 private CensusContextFactory censusFactory;
140
Kun Zhangefac6792015-10-22 14:59:44 -0700141 protected AbstractManagedChannelImplBuilder(String target) {
Carl Mastrangelo12854772016-08-12 14:52:00 -0700142 this.target = Preconditions.checkNotNull(target, "target");
Kun Zhang942f4c92015-09-04 17:21:44 -0700143 this.directServerAddress = null;
144 }
145
Kun Zhang631a9d52016-06-02 16:47:36 -0700146 /**
147 * Returns a target string for the SocketAddress. It is only used as a placeholder, because
148 * DirectAddressNameResolverFactory will not actually try to use it. However, it must be a valid
149 * URI.
150 */
151 @VisibleForTesting
152 static String makeTargetStringForDirectAddress(SocketAddress address) {
153 try {
154 return new URI(DIRECT_ADDRESS_SCHEME, "", "/" + address, null).toString();
155 } catch (URISyntaxException e) {
156 // It should not happen.
157 throw new RuntimeException(e);
158 }
159 }
160
Kun Zhang942f4c92015-09-04 17:21:44 -0700161 protected AbstractManagedChannelImplBuilder(SocketAddress directServerAddress, String authority) {
Kun Zhang631a9d52016-06-02 16:47:36 -0700162 this.target = makeTargetStringForDirectAddress(directServerAddress);
Kun Zhang942f4c92015-09-04 17:21:44 -0700163 this.directServerAddress = directServerAddress;
164 this.nameResolverFactory = new DirectAddressNameResolverFactory(directServerAddress, authority);
165 }
166
Eric Anderson6122daf2015-09-03 12:14:30 -0700167 @Override
buchgr602473d2015-11-11 12:53:08 +0100168 public final T directExecutor() {
169 return executor(MoreExecutors.directExecutor());
170 }
171
172 @Override
Louis Ryan6a782a02015-09-03 14:27:48 -0700173 public final T executor(Executor executor) {
nmittler777e9282015-08-19 10:01:52 -0700174 this.executor = executor;
Eric Anderson0df3d5e2015-06-25 18:00:00 -0700175 return thisT();
176 }
177
Eric Anderson6122daf2015-09-03 12:14:30 -0700178 @Override
nmittlerb687bdc2015-08-31 16:13:39 -0700179 public final T intercept(List<ClientInterceptor> interceptors) {
Eric Anderson0df3d5e2015-06-25 18:00:00 -0700180 this.interceptors.addAll(interceptors);
181 return thisT();
182 }
183
Eric Anderson6122daf2015-09-03 12:14:30 -0700184 @Override
nmittlerb687bdc2015-08-31 16:13:39 -0700185 public final T intercept(ClientInterceptor... interceptors) {
Eric Anderson0df3d5e2015-06-25 18:00:00 -0700186 return intercept(Arrays.asList(interceptors));
187 }
188
Kun Zhang942f4c92015-09-04 17:21:44 -0700189 @Override
190 public final T nameResolverFactory(NameResolver.Factory resolverFactory) {
191 Preconditions.checkState(directServerAddress == null,
192 "directServerAddress is set (%s), which forbids the use of NameResolverFactory",
193 directServerAddress);
194 this.nameResolverFactory = resolverFactory;
195 return thisT();
196 }
197
198 @Override
199 public final T loadBalancerFactory(LoadBalancer.Factory loadBalancerFactory) {
200 Preconditions.checkState(directServerAddress == null,
201 "directServerAddress is set (%s), which forbids the use of LoadBalancerFactory",
202 directServerAddress);
203 this.loadBalancerFactory = loadBalancerFactory;
204 return thisT();
205 }
206
Carl Mastrangelo82a79d82015-12-07 14:40:11 -0800207 @Override
Carl Mastrangelo82a79d82015-12-07 14:40:11 -0800208 public final T decompressorRegistry(DecompressorRegistry registry) {
209 this.decompressorRegistry = registry;
210 return thisT();
211 }
212
213 @Override
Carl Mastrangelo82a79d82015-12-07 14:40:11 -0800214 public final T compressorRegistry(CompressorRegistry registry) {
215 this.compressorRegistry = registry;
216 return thisT();
217 }
218
Eric Anderson6122daf2015-09-03 12:14:30 -0700219 @Override
Carl Mastrangelo1cc76d82016-05-24 16:29:26 -0700220 public final T userAgent(@Nullable String userAgent) {
nmittler8c1d38a2015-06-01 08:31:00 -0700221 this.userAgent = userAgent;
nmittlerb687bdc2015-08-31 16:13:39 -0700222 return thisT();
nmittler8c1d38a2015-06-01 08:31:00 -0700223 }
224
Eric Anderson6122daf2015-09-03 12:14:30 -0700225 @Override
Kun Zhang942f4c92015-09-04 17:21:44 -0700226 public final T overrideAuthority(String authority) {
227 this.authorityOverride = checkAuthority(authority);
228 return thisT();
229 }
230
Kun Zhang527fd672016-06-17 09:47:41 -0700231 @Override
232 public final T idleTimeout(long value, TimeUnit unit) {
233 checkArgument(value > 0, "idle timeout is %s, but must be positive", value);
234 // We convert to the largest unit to avoid overflow
235 if (unit.toDays(value) >= IDLE_MODE_MAX_TIMEOUT_DAYS) {
236 // This disables idle mode
237 this.idleTimeoutMillis = ManagedChannelImpl.IDLE_TIMEOUT_MILLIS_DISABLE;
238 } else {
239 this.idleTimeoutMillis = Math.max(unit.toMillis(value), IDLE_MODE_MIN_TIMEOUT_MILLIS);
240 }
241 return thisT();
242 }
243
Kun Zhang132f7a92016-10-06 17:15:24 -0700244 /**
245 * Override the default Census implementation. This is meant to be used in tests.
246 */
247 @VisibleForTesting
248 @Internal
249 public T censusContextFactory(CensusContextFactory censusFactory) {
250 this.censusFactory = censusFactory;
251 return thisT();
252 }
253
Kun Zhang527fd672016-06-17 09:47:41 -0700254 @VisibleForTesting
255 final long getIdleTimeoutMillis() {
256 return idleTimeoutMillis;
257 }
258
Kun Zhang942f4c92015-09-04 17:21:44 -0700259 /**
260 * Verifies the authority is valid. This method exists as an escape hatch for putting in an
261 * authority that is valid, but would fail the default validation provided by this
262 * implementation.
263 */
264 protected String checkAuthority(String authority) {
265 return GrpcUtil.checkAuthority(authority);
266 }
267
268 @Override
nmittlerb687bdc2015-08-31 16:13:39 -0700269 public ManagedChannelImpl build() {
Sky Ao1d8aefa2016-04-18 23:43:30 +0800270 ClientTransportFactory transportFactory = buildTransportFactory();
271 if (authorityOverride != null) {
272 transportFactory = new AuthorityOverridingTransportFactory(
273 transportFactory, authorityOverride);
274 }
Eric Andersonbfcb04c2016-07-11 10:02:23 -0700275 NameResolver.Factory nameResolverFactory = this.nameResolverFactory;
276 if (nameResolverFactory == null) {
277 // Avoid loading the provider unless necessary, as a way to workaround a possibly-costly
278 // and poorly optimized getResource() call on Android. If any other piece of code calls
279 // getResource(), then this shouldn't be a problem unless called on the UI thread.
280 nameResolverFactory = NameResolverProvider.asFactory();
281 }
Kun Zhang942f4c92015-09-04 17:21:44 -0700282 return new ManagedChannelImpl(
283 target,
Eric Andersona40b6862016-03-25 10:23:58 -0700284 // TODO(carl-mastrangelo): Allow clients to pass this in
285 new ExponentialBackoffPolicy.Provider(),
Eric Andersonbfcb04c2016-07-11 10:02:23 -0700286 nameResolverFactory,
Kun Zhangedd57c92015-10-27 12:47:29 -0700287 getNameResolverParams(),
Lukasz Strzalkowski577164c2016-08-23 00:40:09 +0200288 firstNonNull(loadBalancerFactory, PickFirstBalancerFactory.getInstance()),
Carl Mastrangelo82a79d82015-12-07 14:40:11 -0800289 transportFactory,
290 firstNonNull(decompressorRegistry, DecompressorRegistry.getDefaultInstance()),
291 firstNonNull(compressorRegistry, CompressorRegistry.getDefaultInstance()),
Kun Zhang527fd672016-06-17 09:47:41 -0700292 GrpcUtil.TIMER_SERVICE, GrpcUtil.STOPWATCH_SUPPLIER, idleTimeoutMillis,
Kun Zhang132f7a92016-10-06 17:15:24 -0700293 executor, userAgent, interceptors,
294 firstNonNull(censusFactory,
295 firstNonNull(Census.getCensusContextFactory(), NoopCensusContextFactory.INSTANCE)));
zhangkun8d6d12e2014-10-15 13:04:19 -0700296 }
297
298 /**
Kun Zhangedd57c92015-10-27 12:47:29 -0700299 * Subclasses should override this method to provide the {@link ClientTransportFactory}
300 * appropriate for this channel. This method is meant for Transport implementors and should not
301 * be used by normal users.
zhangkun8d6d12e2014-10-15 13:04:19 -0700302 */
nmittler777e9282015-08-19 10:01:52 -0700303 protected abstract ClientTransportFactory buildTransportFactory();
Kun Zhang942f4c92015-09-04 17:21:44 -0700304
Kun Zhangedd57c92015-10-27 12:47:29 -0700305 /**
306 * Subclasses can override this method to provide additional parameters to {@link
307 * NameResolver.Factory#newNameResolver}. The default implementation returns {@link
Carl Mastrangelo82a79d82015-12-07 14:40:11 -0800308 * Attributes#EMPTY}.
Kun Zhangedd57c92015-10-27 12:47:29 -0700309 */
310 protected Attributes getNameResolverParams() {
311 return Attributes.EMPTY;
312 }
313
Kun Zhang942f4c92015-09-04 17:21:44 -0700314 private static class AuthorityOverridingTransportFactory implements ClientTransportFactory {
315 final ClientTransportFactory factory;
Sky Ao1d8aefa2016-04-18 23:43:30 +0800316 final String authorityOverride;
Kun Zhang942f4c92015-09-04 17:21:44 -0700317
318 AuthorityOverridingTransportFactory(
Sky Ao1d8aefa2016-04-18 23:43:30 +0800319 ClientTransportFactory factory, String authorityOverride) {
320 this.factory = Preconditions.checkNotNull(factory, "factory should not be null");
321 this.authorityOverride = Preconditions.checkNotNull(
322 authorityOverride, "authorityOverride should not be null");
Kun Zhang942f4c92015-09-04 17:21:44 -0700323 }
324
325 @Override
Kun Zhang432cec72016-05-29 14:43:10 -0700326 public ConnectionClientTransport newClientTransport(SocketAddress serverAddress,
Carl Mastrangelo1cc76d82016-05-24 16:29:26 -0700327 String authority, @Nullable String userAgent) {
328 return factory.newClientTransport(serverAddress, authorityOverride, userAgent);
Kun Zhang942f4c92015-09-04 17:21:44 -0700329 }
330
331 @Override
buchgr3c68c052016-03-17 00:14:43 +0100332 public void close() {
333 factory.close();
Kun Zhang942f4c92015-09-04 17:21:44 -0700334 }
335 }
336
337 private static class DirectAddressNameResolverFactory extends NameResolver.Factory {
338 final SocketAddress address;
339 final String authority;
340
341 DirectAddressNameResolverFactory(SocketAddress address, String authority) {
342 this.address = address;
343 this.authority = authority;
344 }
345
346 @Override
Kun Zhangedd57c92015-10-27 12:47:29 -0700347 public NameResolver newNameResolver(URI notUsedUri, Attributes params) {
Kun Zhang942f4c92015-09-04 17:21:44 -0700348 return new NameResolver() {
349 @Override
350 public String getServiceAuthority() {
351 return authority;
352 }
353
354 @Override
355 public void start(final Listener listener) {
Lukasz Strzalkowski23652c52016-08-19 16:56:56 +0200356 listener.onUpdate(Collections.singletonList(
357 ResolvedServerInfoGroup.builder().add(new ResolvedServerInfo(address)).build()),
Kun Zhang942f4c92015-09-04 17:21:44 -0700358 Attributes.EMPTY);
359 }
360
361 @Override
362 public void shutdown() {}
363 };
364 }
Kun Zhang16247152015-12-08 17:52:05 -0800365
366 @Override
367 public String getDefaultScheme() {
368 return DIRECT_ADDRESS_SCHEME;
369 }
Kun Zhang942f4c92015-09-04 17:21:44 -0700370 }
zhangkun8d6d12e2014-10-15 13:04:19 -0700371}