blob: a403e262e799925bd243cd81a8a7513a1eeb2ae1 [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 Zhang631a9d52016-06-02 16:47:36 -070037import com.google.common.annotations.VisibleForTesting;
Kun Zhang942f4c92015-09-04 17:21:44 -070038import com.google.common.base.Preconditions;
buchgr602473d2015-11-11 12:53:08 +010039import com.google.common.util.concurrent.MoreExecutors;
Kun Zhangcce8eac2017-01-05 10:48:13 -080040import com.google.instrumentation.stats.Stats;
41import com.google.instrumentation.stats.StatsContextFactory;
Kun Zhang942f4c92015-09-04 17:21:44 -070042import io.grpc.Attributes;
43import io.grpc.ClientInterceptor;
Carl Mastrangelo82a79d82015-12-07 14:40:11 -080044import io.grpc.CompressorRegistry;
45import io.grpc.DecompressorRegistry;
Kun Zhanga9bd9472017-02-21 17:11:03 -080046import io.grpc.LoadBalancer;
Kun Zhangd17a7b52017-01-10 15:30:12 -080047import io.grpc.ManagedChannel;
Kun Zhang942f4c92015-09-04 17:21:44 -070048import io.grpc.ManagedChannelBuilder;
49import io.grpc.NameResolver;
Eric Anderson56a29382016-06-11 11:55:49 -070050import io.grpc.NameResolverProvider;
Kun Zhanga9bd9472017-02-21 17:11:03 -080051import io.grpc.PickFirstBalancerFactory;
Kun Zhang942f4c92015-09-04 17:21:44 -070052import io.grpc.ResolvedServerInfo;
Lukasz Strzalkowski23652c52016-08-19 16:56:56 +020053import io.grpc.ResolvedServerInfoGroup;
Kun Zhang942f4c92015-09-04 17:21:44 -070054import java.net.SocketAddress;
55import java.net.URI;
Kun Zhang631a9d52016-06-02 16:47:36 -070056import java.net.URISyntaxException;
Eric Anderson0df3d5e2015-06-25 18:00:00 -070057import java.util.ArrayList;
58import java.util.Arrays;
Kun Zhang942f4c92015-09-04 17:21:44 -070059import java.util.Collections;
Eric Anderson0df3d5e2015-06-25 18:00:00 -070060import java.util.List;
Louis Ryan6a782a02015-09-03 14:27:48 -070061import java.util.concurrent.Executor;
Kun Zhang527fd672016-06-17 09:47:41 -070062import java.util.concurrent.TimeUnit;
zhangkun8d6d12e2014-10-15 13:04:19 -070063import javax.annotation.Nullable;
64
65/**
66 * The base class for channel builders.
nathanmittler0304b3d2014-10-24 13:39:13 -070067 *
nmittlerb687bdc2015-08-31 16:13:39 -070068 * @param <T> The concrete type of this builder.
zhangkun8d6d12e2014-10-15 13:04:19 -070069 */
nmittlerb687bdc2015-08-31 16:13:39 -070070public abstract class AbstractManagedChannelImplBuilder
71 <T extends AbstractManagedChannelImplBuilder<T>> extends ManagedChannelBuilder<T> {
Kun Zhang16247152015-12-08 17:52:05 -080072 private static final String DIRECT_ADDRESS_SCHEME = "directaddress";
Eric Andersonaeeebb72014-12-19 16:41:03 -080073
Kun Zhang527fd672016-06-17 09:47:41 -070074 /**
75 * An idle timeout larger than this would disable idle mode.
76 */
77 @VisibleForTesting
78 static final long IDLE_MODE_MAX_TIMEOUT_DAYS = 30;
79
80 /**
Kun Zhangd74091f2016-09-16 22:34:27 -070081 * The default idle timeout.
82 */
83 @VisibleForTesting
84 static final long IDLE_MODE_DEFAULT_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(30);
85
86 /**
Kun Zhang527fd672016-06-17 09:47:41 -070087 * An idle timeout smaller than this would be capped to it.
88 */
89 @VisibleForTesting
90 static final long IDLE_MODE_MIN_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(1);
91
ejona7235a392015-01-13 13:38:54 -080092 @Nullable
Louis Ryan6a782a02015-09-03 14:27:48 -070093 private Executor executor;
Kun Zhangd17a7b52017-01-10 15:30:12 -080094
Eric Anderson0df3d5e2015-06-25 18:00:00 -070095 private final List<ClientInterceptor> interceptors = new ArrayList<ClientInterceptor>();
zhangkun8d6d12e2014-10-15 13:04:19 -070096
Kun Zhangefac6792015-10-22 14:59:44 -070097 private final String target;
Kun Zhang942f4c92015-09-04 17:21:44 -070098
99 @Nullable
100 private final SocketAddress directServerAddress;
101
nmittler8c1d38a2015-06-01 08:31:00 -0700102 @Nullable
103 private String userAgent;
104
Kun Zhang942f4c92015-09-04 17:21:44 -0700105 @Nullable
106 private String authorityOverride;
107
108 @Nullable
109 private NameResolver.Factory nameResolverFactory;
110
Kun Zhanga9bd9472017-02-21 17:11:03 -0800111 private LoadBalancer.Factory loadBalancerFactory;
Kun Zhang942f4c92015-09-04 17:21:44 -0700112
Carl Mastrangelo82a79d82015-12-07 14:40:11 -0800113 @Nullable
114 private DecompressorRegistry decompressorRegistry;
115
116 @Nullable
117 private CompressorRegistry compressorRegistry;
118
Kun Zhangd74091f2016-09-16 22:34:27 -0700119 private long idleTimeoutMillis = IDLE_MODE_DEFAULT_TIMEOUT_MILLIS;
Kun Zhang527fd672016-06-17 09:47:41 -0700120
Carl Mastrangelofdd062c2016-10-26 16:55:41 -0700121 private int maxInboundMessageSize = GrpcUtil.DEFAULT_MAX_MESSAGE_SIZE;
122
123 // Can be overriden by subclasses.
124 @Override
125 public T maxInboundMessageSize(int max) {
126 checkArgument(max >= 0, "negative max");
127 maxInboundMessageSize = max;
128 return thisT();
129 }
130
131 protected final int maxInboundMessageSize() {
132 return maxInboundMessageSize;
133 }
134
Kun Zhang132f7a92016-10-06 17:15:24 -0700135 @Nullable
Kun Zhangcce8eac2017-01-05 10:48:13 -0800136 private StatsContextFactory statsFactory;
Kun Zhang132f7a92016-10-06 17:15:24 -0700137
Kun Zhangefac6792015-10-22 14:59:44 -0700138 protected AbstractManagedChannelImplBuilder(String target) {
Carl Mastrangelo12854772016-08-12 14:52:00 -0700139 this.target = Preconditions.checkNotNull(target, "target");
Kun Zhang942f4c92015-09-04 17:21:44 -0700140 this.directServerAddress = null;
141 }
142
Kun Zhang631a9d52016-06-02 16:47:36 -0700143 /**
144 * Returns a target string for the SocketAddress. It is only used as a placeholder, because
145 * DirectAddressNameResolverFactory will not actually try to use it. However, it must be a valid
146 * URI.
147 */
148 @VisibleForTesting
149 static String makeTargetStringForDirectAddress(SocketAddress address) {
150 try {
151 return new URI(DIRECT_ADDRESS_SCHEME, "", "/" + address, null).toString();
152 } catch (URISyntaxException e) {
153 // It should not happen.
154 throw new RuntimeException(e);
155 }
156 }
157
Kun Zhang942f4c92015-09-04 17:21:44 -0700158 protected AbstractManagedChannelImplBuilder(SocketAddress directServerAddress, String authority) {
Kun Zhang631a9d52016-06-02 16:47:36 -0700159 this.target = makeTargetStringForDirectAddress(directServerAddress);
Kun Zhang942f4c92015-09-04 17:21:44 -0700160 this.directServerAddress = directServerAddress;
161 this.nameResolverFactory = new DirectAddressNameResolverFactory(directServerAddress, authority);
162 }
163
Eric Anderson6122daf2015-09-03 12:14:30 -0700164 @Override
buchgr602473d2015-11-11 12:53:08 +0100165 public final T directExecutor() {
166 return executor(MoreExecutors.directExecutor());
167 }
168
169 @Override
Louis Ryan6a782a02015-09-03 14:27:48 -0700170 public final T executor(Executor executor) {
nmittler777e9282015-08-19 10:01:52 -0700171 this.executor = executor;
Eric Anderson0df3d5e2015-06-25 18:00:00 -0700172 return thisT();
173 }
174
Eric Anderson6122daf2015-09-03 12:14:30 -0700175 @Override
nmittlerb687bdc2015-08-31 16:13:39 -0700176 public final T intercept(List<ClientInterceptor> interceptors) {
Eric Anderson0df3d5e2015-06-25 18:00:00 -0700177 this.interceptors.addAll(interceptors);
178 return thisT();
179 }
180
Eric Anderson6122daf2015-09-03 12:14:30 -0700181 @Override
nmittlerb687bdc2015-08-31 16:13:39 -0700182 public final T intercept(ClientInterceptor... interceptors) {
Eric Anderson0df3d5e2015-06-25 18:00:00 -0700183 return intercept(Arrays.asList(interceptors));
184 }
185
Kun Zhang942f4c92015-09-04 17:21:44 -0700186 @Override
187 public final T nameResolverFactory(NameResolver.Factory resolverFactory) {
188 Preconditions.checkState(directServerAddress == null,
189 "directServerAddress is set (%s), which forbids the use of NameResolverFactory",
190 directServerAddress);
191 this.nameResolverFactory = resolverFactory;
192 return thisT();
193 }
194
195 @Override
Kun Zhanga9bd9472017-02-21 17:11:03 -0800196 public final T loadBalancerFactory(LoadBalancer.Factory loadBalancerFactory) {
Kun Zhang942f4c92015-09-04 17:21:44 -0700197 Preconditions.checkState(directServerAddress == null,
Kun Zhanga9bd9472017-02-21 17:11:03 -0800198 "directServerAddress is set (%s), which forbids the use of LoadBalancer.Factory",
Kun Zhang942f4c92015-09-04 17:21:44 -0700199 directServerAddress);
200 this.loadBalancerFactory = loadBalancerFactory;
Kun Zhangd17a7b52017-01-10 15:30:12 -0800201 return thisT();
202 }
203
Carl Mastrangelo82a79d82015-12-07 14:40:11 -0800204 @Override
Carl Mastrangelo82a79d82015-12-07 14:40:11 -0800205 public final T decompressorRegistry(DecompressorRegistry registry) {
206 this.decompressorRegistry = registry;
207 return thisT();
208 }
209
210 @Override
Carl Mastrangelo82a79d82015-12-07 14:40:11 -0800211 public final T compressorRegistry(CompressorRegistry registry) {
212 this.compressorRegistry = registry;
213 return thisT();
214 }
215
Eric Anderson6122daf2015-09-03 12:14:30 -0700216 @Override
Carl Mastrangelo1cc76d82016-05-24 16:29:26 -0700217 public final T userAgent(@Nullable String userAgent) {
nmittler8c1d38a2015-06-01 08:31:00 -0700218 this.userAgent = userAgent;
nmittlerb687bdc2015-08-31 16:13:39 -0700219 return thisT();
nmittler8c1d38a2015-06-01 08:31:00 -0700220 }
221
Eric Anderson6122daf2015-09-03 12:14:30 -0700222 @Override
Kun Zhang942f4c92015-09-04 17:21:44 -0700223 public final T overrideAuthority(String authority) {
224 this.authorityOverride = checkAuthority(authority);
225 return thisT();
226 }
227
Kun Zhang527fd672016-06-17 09:47:41 -0700228 @Override
229 public final T idleTimeout(long value, TimeUnit unit) {
230 checkArgument(value > 0, "idle timeout is %s, but must be positive", value);
231 // We convert to the largest unit to avoid overflow
232 if (unit.toDays(value) >= IDLE_MODE_MAX_TIMEOUT_DAYS) {
233 // This disables idle mode
Kun Zhanga9bd9472017-02-21 17:11:03 -0800234 this.idleTimeoutMillis = ManagedChannelImpl.IDLE_TIMEOUT_MILLIS_DISABLE;
Kun Zhang527fd672016-06-17 09:47:41 -0700235 } else {
236 this.idleTimeoutMillis = Math.max(unit.toMillis(value), IDLE_MODE_MIN_TIMEOUT_MILLIS);
237 }
238 return thisT();
239 }
240
Kun Zhang132f7a92016-10-06 17:15:24 -0700241 /**
Kun Zhang737cd162017-01-20 17:20:44 -0800242 * Override the default stats implementation.
Kun Zhang132f7a92016-10-06 17:15:24 -0700243 */
244 @VisibleForTesting
Kun Zhang737cd162017-01-20 17:20:44 -0800245 protected T statsContextFactory(StatsContextFactory statsFactory) {
Kun Zhangcce8eac2017-01-05 10:48:13 -0800246 this.statsFactory = statsFactory;
Kun Zhang132f7a92016-10-06 17:15:24 -0700247 return thisT();
248 }
249
Kun Zhang527fd672016-06-17 09:47:41 -0700250 @VisibleForTesting
251 final long getIdleTimeoutMillis() {
252 return idleTimeoutMillis;
253 }
254
Kun Zhang942f4c92015-09-04 17:21:44 -0700255 /**
256 * Verifies the authority is valid. This method exists as an escape hatch for putting in an
257 * authority that is valid, but would fail the default validation provided by this
258 * implementation.
259 */
260 protected String checkAuthority(String authority) {
261 return GrpcUtil.checkAuthority(authority);
262 }
263
264 @Override
Kun Zhangd17a7b52017-01-10 15:30:12 -0800265 public ManagedChannel build() {
Sky Ao1d8aefa2016-04-18 23:43:30 +0800266 ClientTransportFactory transportFactory = buildTransportFactory();
267 if (authorityOverride != null) {
268 transportFactory = new AuthorityOverridingTransportFactory(
269 transportFactory, authorityOverride);
270 }
Eric Andersonbfcb04c2016-07-11 10:02:23 -0700271 NameResolver.Factory nameResolverFactory = this.nameResolverFactory;
272 if (nameResolverFactory == null) {
273 // Avoid loading the provider unless necessary, as a way to workaround a possibly-costly
274 // and poorly optimized getResource() call on Android. If any other piece of code calls
275 // getResource(), then this shouldn't be a problem unless called on the UI thread.
276 nameResolverFactory = NameResolverProvider.asFactory();
277 }
Kun Zhanga9bd9472017-02-21 17:11:03 -0800278 return new ManagedChannelImpl(
Kun Zhanga6b1d892017-02-21 14:26:23 -0800279 target,
280 // TODO(carl-mastrangelo): Allow clients to pass this in
281 new ExponentialBackoffPolicy.Provider(),
282 nameResolverFactory,
283 getNameResolverParams(),
Kun Zhanga9bd9472017-02-21 17:11:03 -0800284 firstNonNull(loadBalancerFactory, PickFirstBalancerFactory.getInstance()),
Kun Zhanga6b1d892017-02-21 14:26:23 -0800285 transportFactory,
286 firstNonNull(decompressorRegistry, DecompressorRegistry.getDefaultInstance()),
287 firstNonNull(compressorRegistry, CompressorRegistry.getDefaultInstance()),
288 SharedResourcePool.forResource(GrpcUtil.TIMER_SERVICE),
289 getExecutorPool(executor),
290 SharedResourcePool.forResource(GrpcUtil.SHARED_CHANNEL_EXECUTOR),
Kun Zhanga9bd9472017-02-21 17:11:03 -0800291 GrpcUtil.STOPWATCH_SUPPLIER,
292 idleTimeoutMillis,
293 userAgent,
294 interceptors,
295 firstNonNull(
296 statsFactory,
Kun Zhanga6b1d892017-02-21 14:26:23 -0800297 firstNonNull(Stats.getStatsContextFactory(), NoopStatsContextFactory.INSTANCE)));
zhangkun8d6d12e2014-10-15 13:04:19 -0700298 }
299
300 /**
Kun Zhangedd57c92015-10-27 12:47:29 -0700301 * Subclasses should override this method to provide the {@link ClientTransportFactory}
302 * appropriate for this channel. This method is meant for Transport implementors and should not
303 * be used by normal users.
zhangkun8d6d12e2014-10-15 13:04:19 -0700304 */
nmittler777e9282015-08-19 10:01:52 -0700305 protected abstract ClientTransportFactory buildTransportFactory();
Kun Zhang942f4c92015-09-04 17:21:44 -0700306
Kun Zhangedd57c92015-10-27 12:47:29 -0700307 /**
308 * Subclasses can override this method to provide additional parameters to {@link
309 * NameResolver.Factory#newNameResolver}. The default implementation returns {@link
Carl Mastrangelo82a79d82015-12-07 14:40:11 -0800310 * Attributes#EMPTY}.
Kun Zhangedd57c92015-10-27 12:47:29 -0700311 */
312 protected Attributes getNameResolverParams() {
313 return Attributes.EMPTY;
314 }
315
Kun Zhangd17a7b52017-01-10 15:30:12 -0800316 private static ObjectPool<? extends Executor> getExecutorPool(final @Nullable Executor executor) {
317 if (executor != null) {
318 return new ObjectPool<Executor>() {
319 @Override
320 public Executor getObject() {
321 return executor;
322 }
323
324 @Override
325 public Executor returnObject(Object returned) {
326 return null;
327 }
328 };
329 } else {
330 return SharedResourcePool.forResource(GrpcUtil.SHARED_CHANNEL_EXECUTOR);
331 }
332 }
333
Kun Zhang942f4c92015-09-04 17:21:44 -0700334 private static class AuthorityOverridingTransportFactory implements ClientTransportFactory {
335 final ClientTransportFactory factory;
Sky Ao1d8aefa2016-04-18 23:43:30 +0800336 final String authorityOverride;
Kun Zhang942f4c92015-09-04 17:21:44 -0700337
338 AuthorityOverridingTransportFactory(
Sky Ao1d8aefa2016-04-18 23:43:30 +0800339 ClientTransportFactory factory, String authorityOverride) {
340 this.factory = Preconditions.checkNotNull(factory, "factory should not be null");
341 this.authorityOverride = Preconditions.checkNotNull(
342 authorityOverride, "authorityOverride should not be null");
Kun Zhang942f4c92015-09-04 17:21:44 -0700343 }
344
345 @Override
Kun Zhang432cec72016-05-29 14:43:10 -0700346 public ConnectionClientTransport newClientTransport(SocketAddress serverAddress,
Carl Mastrangelo1cc76d82016-05-24 16:29:26 -0700347 String authority, @Nullable String userAgent) {
348 return factory.newClientTransport(serverAddress, authorityOverride, userAgent);
Kun Zhang942f4c92015-09-04 17:21:44 -0700349 }
350
351 @Override
buchgr3c68c052016-03-17 00:14:43 +0100352 public void close() {
353 factory.close();
Kun Zhang942f4c92015-09-04 17:21:44 -0700354 }
355 }
356
357 private static class DirectAddressNameResolverFactory extends NameResolver.Factory {
358 final SocketAddress address;
359 final String authority;
360
361 DirectAddressNameResolverFactory(SocketAddress address, String authority) {
362 this.address = address;
363 this.authority = authority;
364 }
365
366 @Override
Kun Zhangedd57c92015-10-27 12:47:29 -0700367 public NameResolver newNameResolver(URI notUsedUri, Attributes params) {
Kun Zhang942f4c92015-09-04 17:21:44 -0700368 return new NameResolver() {
369 @Override
370 public String getServiceAuthority() {
371 return authority;
372 }
373
374 @Override
375 public void start(final Listener listener) {
Lukasz Strzalkowski23652c52016-08-19 16:56:56 +0200376 listener.onUpdate(Collections.singletonList(
377 ResolvedServerInfoGroup.builder().add(new ResolvedServerInfo(address)).build()),
Kun Zhang942f4c92015-09-04 17:21:44 -0700378 Attributes.EMPTY);
379 }
380
381 @Override
382 public void shutdown() {}
383 };
384 }
Kun Zhang16247152015-12-08 17:52:05 -0800385
386 @Override
387 public String getDefaultScheme() {
388 return DIRECT_ADDRESS_SCHEME;
389 }
Kun Zhang942f4c92015-09-04 17:21:44 -0700390 }
Carl Mastrangelo84934982017-01-11 12:46:47 -0800391
392 /**
393 * Returns the correctly typed version of the builder.
394 */
395 private T thisT() {
396 @SuppressWarnings("unchecked")
397 T thisT = (T) this;
398 return thisT;
399 }
zhangkun8d6d12e2014-10-15 13:04:19 -0700400}