blob: 02c202d97f9ff8b8db3916eb487a7d9a973c6df9 [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 Zhang418d52d2017-03-22 18:29:31 -070046import io.grpc.EquivalentAddressGroup;
Kun Zhanga9bd9472017-02-21 17:11:03 -080047import io.grpc.LoadBalancer;
Kun Zhangd17a7b52017-01-10 15:30:12 -080048import io.grpc.ManagedChannel;
Kun Zhang942f4c92015-09-04 17:21:44 -070049import io.grpc.ManagedChannelBuilder;
50import io.grpc.NameResolver;
Eric Anderson56a29382016-06-11 11:55:49 -070051import io.grpc.NameResolverProvider;
Kun Zhanga9bd9472017-02-21 17:11:03 -080052import io.grpc.PickFirstBalancerFactory;
Kun Zhang942f4c92015-09-04 17:21:44 -070053import java.net.SocketAddress;
54import java.net.URI;
Kun Zhang631a9d52016-06-02 16:47:36 -070055import java.net.URISyntaxException;
Eric Anderson0df3d5e2015-06-25 18:00:00 -070056import java.util.ArrayList;
57import java.util.Arrays;
Kun Zhang942f4c92015-09-04 17:21:44 -070058import java.util.Collections;
Eric Anderson0df3d5e2015-06-25 18:00:00 -070059import java.util.List;
Louis Ryan6a782a02015-09-03 14:27:48 -070060import java.util.concurrent.Executor;
Kun Zhang527fd672016-06-17 09:47:41 -070061import java.util.concurrent.TimeUnit;
zhangkun8d6d12e2014-10-15 13:04:19 -070062import javax.annotation.Nullable;
63
64/**
65 * The base class for channel builders.
nathanmittler0304b3d2014-10-24 13:39:13 -070066 *
nmittlerb687bdc2015-08-31 16:13:39 -070067 * @param <T> The concrete type of this builder.
zhangkun8d6d12e2014-10-15 13:04:19 -070068 */
nmittlerb687bdc2015-08-31 16:13:39 -070069public abstract class AbstractManagedChannelImplBuilder
70 <T extends AbstractManagedChannelImplBuilder<T>> extends ManagedChannelBuilder<T> {
Kun Zhang16247152015-12-08 17:52:05 -080071 private static final String DIRECT_ADDRESS_SCHEME = "directaddress";
Eric Andersonaeeebb72014-12-19 16:41:03 -080072
Kun Zhang527fd672016-06-17 09:47:41 -070073 /**
74 * An idle timeout larger than this would disable idle mode.
75 */
76 @VisibleForTesting
77 static final long IDLE_MODE_MAX_TIMEOUT_DAYS = 30;
78
79 /**
Kun Zhangd74091f2016-09-16 22:34:27 -070080 * The default idle timeout.
81 */
82 @VisibleForTesting
83 static final long IDLE_MODE_DEFAULT_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(30);
84
85 /**
Kun Zhang527fd672016-06-17 09:47:41 -070086 * An idle timeout smaller than this would be capped to it.
87 */
88 @VisibleForTesting
89 static final long IDLE_MODE_MIN_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(1);
90
ejona7235a392015-01-13 13:38:54 -080091 @Nullable
Louis Ryan6a782a02015-09-03 14:27:48 -070092 private Executor executor;
Kun Zhangd17a7b52017-01-10 15:30:12 -080093
Eric Anderson0df3d5e2015-06-25 18:00:00 -070094 private final List<ClientInterceptor> interceptors = new ArrayList<ClientInterceptor>();
zhangkun8d6d12e2014-10-15 13:04:19 -070095
Kun Zhangefac6792015-10-22 14:59:44 -070096 private final String target;
Kun Zhang942f4c92015-09-04 17:21:44 -070097
98 @Nullable
99 private final SocketAddress directServerAddress;
100
nmittler8c1d38a2015-06-01 08:31:00 -0700101 @Nullable
102 private String userAgent;
103
Kun Zhang942f4c92015-09-04 17:21:44 -0700104 @Nullable
105 private String authorityOverride;
106
107 @Nullable
108 private NameResolver.Factory nameResolverFactory;
109
Kun Zhanga9bd9472017-02-21 17:11:03 -0800110 private LoadBalancer.Factory loadBalancerFactory;
Kun Zhang942f4c92015-09-04 17:21:44 -0700111
Carl Mastrangelo82a79d82015-12-07 14:40:11 -0800112 @Nullable
113 private DecompressorRegistry decompressorRegistry;
114
115 @Nullable
116 private CompressorRegistry compressorRegistry;
117
Kun Zhangd74091f2016-09-16 22:34:27 -0700118 private long idleTimeoutMillis = IDLE_MODE_DEFAULT_TIMEOUT_MILLIS;
Kun Zhang527fd672016-06-17 09:47:41 -0700119
Carl Mastrangelofdd062c2016-10-26 16:55:41 -0700120 private int maxInboundMessageSize = GrpcUtil.DEFAULT_MAX_MESSAGE_SIZE;
121
122 // Can be overriden by subclasses.
123 @Override
124 public T maxInboundMessageSize(int max) {
125 checkArgument(max >= 0, "negative max");
126 maxInboundMessageSize = max;
127 return thisT();
128 }
129
130 protected final int maxInboundMessageSize() {
131 return maxInboundMessageSize;
132 }
133
Kun Zhang132f7a92016-10-06 17:15:24 -0700134 @Nullable
Kun Zhangcce8eac2017-01-05 10:48:13 -0800135 private StatsContextFactory statsFactory;
Kun Zhang132f7a92016-10-06 17:15:24 -0700136
Kun Zhangefac6792015-10-22 14:59:44 -0700137 protected AbstractManagedChannelImplBuilder(String target) {
Carl Mastrangelo12854772016-08-12 14:52:00 -0700138 this.target = Preconditions.checkNotNull(target, "target");
Kun Zhang942f4c92015-09-04 17:21:44 -0700139 this.directServerAddress = null;
140 }
141
Kun Zhang631a9d52016-06-02 16:47:36 -0700142 /**
143 * Returns a target string for the SocketAddress. It is only used as a placeholder, because
144 * DirectAddressNameResolverFactory will not actually try to use it. However, it must be a valid
145 * URI.
146 */
147 @VisibleForTesting
148 static String makeTargetStringForDirectAddress(SocketAddress address) {
149 try {
150 return new URI(DIRECT_ADDRESS_SCHEME, "", "/" + address, null).toString();
151 } catch (URISyntaxException e) {
152 // It should not happen.
153 throw new RuntimeException(e);
154 }
155 }
156
Kun Zhang942f4c92015-09-04 17:21:44 -0700157 protected AbstractManagedChannelImplBuilder(SocketAddress directServerAddress, String authority) {
Kun Zhang631a9d52016-06-02 16:47:36 -0700158 this.target = makeTargetStringForDirectAddress(directServerAddress);
Kun Zhang942f4c92015-09-04 17:21:44 -0700159 this.directServerAddress = directServerAddress;
160 this.nameResolverFactory = new DirectAddressNameResolverFactory(directServerAddress, authority);
161 }
162
Eric Anderson6122daf2015-09-03 12:14:30 -0700163 @Override
buchgr602473d2015-11-11 12:53:08 +0100164 public final T directExecutor() {
165 return executor(MoreExecutors.directExecutor());
166 }
167
168 @Override
Louis Ryan6a782a02015-09-03 14:27:48 -0700169 public final T executor(Executor executor) {
nmittler777e9282015-08-19 10:01:52 -0700170 this.executor = executor;
Eric Anderson0df3d5e2015-06-25 18:00:00 -0700171 return thisT();
172 }
173
Eric Anderson6122daf2015-09-03 12:14:30 -0700174 @Override
nmittlerb687bdc2015-08-31 16:13:39 -0700175 public final T intercept(List<ClientInterceptor> interceptors) {
Eric Anderson0df3d5e2015-06-25 18:00:00 -0700176 this.interceptors.addAll(interceptors);
177 return thisT();
178 }
179
Eric Anderson6122daf2015-09-03 12:14:30 -0700180 @Override
nmittlerb687bdc2015-08-31 16:13:39 -0700181 public final T intercept(ClientInterceptor... interceptors) {
Eric Anderson0df3d5e2015-06-25 18:00:00 -0700182 return intercept(Arrays.asList(interceptors));
183 }
184
Kun Zhang942f4c92015-09-04 17:21:44 -0700185 @Override
186 public final T nameResolverFactory(NameResolver.Factory resolverFactory) {
187 Preconditions.checkState(directServerAddress == null,
188 "directServerAddress is set (%s), which forbids the use of NameResolverFactory",
189 directServerAddress);
190 this.nameResolverFactory = resolverFactory;
191 return thisT();
192 }
193
194 @Override
Kun Zhanga9bd9472017-02-21 17:11:03 -0800195 public final T loadBalancerFactory(LoadBalancer.Factory loadBalancerFactory) {
Kun Zhang942f4c92015-09-04 17:21:44 -0700196 Preconditions.checkState(directServerAddress == null,
Kun Zhanga9bd9472017-02-21 17:11:03 -0800197 "directServerAddress is set (%s), which forbids the use of LoadBalancer.Factory",
Kun Zhang942f4c92015-09-04 17:21:44 -0700198 directServerAddress);
199 this.loadBalancerFactory = loadBalancerFactory;
Kun Zhangd17a7b52017-01-10 15:30:12 -0800200 return thisT();
201 }
202
Carl Mastrangelo82a79d82015-12-07 14:40:11 -0800203 @Override
Carl Mastrangelo82a79d82015-12-07 14:40:11 -0800204 public final T decompressorRegistry(DecompressorRegistry registry) {
205 this.decompressorRegistry = registry;
206 return thisT();
207 }
208
209 @Override
Carl Mastrangelo82a79d82015-12-07 14:40:11 -0800210 public final T compressorRegistry(CompressorRegistry registry) {
211 this.compressorRegistry = registry;
212 return thisT();
213 }
214
Eric Anderson6122daf2015-09-03 12:14:30 -0700215 @Override
Carl Mastrangelo1cc76d82016-05-24 16:29:26 -0700216 public final T userAgent(@Nullable String userAgent) {
nmittler8c1d38a2015-06-01 08:31:00 -0700217 this.userAgent = userAgent;
nmittlerb687bdc2015-08-31 16:13:39 -0700218 return thisT();
nmittler8c1d38a2015-06-01 08:31:00 -0700219 }
220
Eric Anderson6122daf2015-09-03 12:14:30 -0700221 @Override
Kun Zhang942f4c92015-09-04 17:21:44 -0700222 public final T overrideAuthority(String authority) {
223 this.authorityOverride = checkAuthority(authority);
224 return thisT();
225 }
226
Kun Zhang527fd672016-06-17 09:47:41 -0700227 @Override
228 public final T idleTimeout(long value, TimeUnit unit) {
229 checkArgument(value > 0, "idle timeout is %s, but must be positive", value);
230 // We convert to the largest unit to avoid overflow
231 if (unit.toDays(value) >= IDLE_MODE_MAX_TIMEOUT_DAYS) {
232 // This disables idle mode
Kun Zhanga9bd9472017-02-21 17:11:03 -0800233 this.idleTimeoutMillis = ManagedChannelImpl.IDLE_TIMEOUT_MILLIS_DISABLE;
Kun Zhang527fd672016-06-17 09:47:41 -0700234 } else {
235 this.idleTimeoutMillis = Math.max(unit.toMillis(value), IDLE_MODE_MIN_TIMEOUT_MILLIS);
236 }
237 return thisT();
238 }
239
Kun Zhang132f7a92016-10-06 17:15:24 -0700240 /**
Kun Zhang737cd162017-01-20 17:20:44 -0800241 * Override the default stats implementation.
Kun Zhang132f7a92016-10-06 17:15:24 -0700242 */
243 @VisibleForTesting
Kun Zhang737cd162017-01-20 17:20:44 -0800244 protected T statsContextFactory(StatsContextFactory statsFactory) {
Kun Zhangcce8eac2017-01-05 10:48:13 -0800245 this.statsFactory = statsFactory;
Kun Zhang132f7a92016-10-06 17:15:24 -0700246 return thisT();
247 }
248
Kun Zhang527fd672016-06-17 09:47:41 -0700249 @VisibleForTesting
250 final long getIdleTimeoutMillis() {
251 return idleTimeoutMillis;
252 }
253
Kun Zhang942f4c92015-09-04 17:21:44 -0700254 /**
255 * Verifies the authority is valid. This method exists as an escape hatch for putting in an
256 * authority that is valid, but would fail the default validation provided by this
257 * implementation.
258 */
259 protected String checkAuthority(String authority) {
260 return GrpcUtil.checkAuthority(authority);
261 }
262
263 @Override
Kun Zhangd17a7b52017-01-10 15:30:12 -0800264 public ManagedChannel build() {
Sky Ao1d8aefa2016-04-18 23:43:30 +0800265 ClientTransportFactory transportFactory = buildTransportFactory();
266 if (authorityOverride != null) {
267 transportFactory = new AuthorityOverridingTransportFactory(
268 transportFactory, authorityOverride);
269 }
Eric Andersonbfcb04c2016-07-11 10:02:23 -0700270 NameResolver.Factory nameResolverFactory = this.nameResolverFactory;
271 if (nameResolverFactory == null) {
272 // Avoid loading the provider unless necessary, as a way to workaround a possibly-costly
273 // and poorly optimized getResource() call on Android. If any other piece of code calls
274 // getResource(), then this shouldn't be a problem unless called on the UI thread.
275 nameResolverFactory = NameResolverProvider.asFactory();
276 }
Kun Zhanga9bd9472017-02-21 17:11:03 -0800277 return new ManagedChannelImpl(
Kun Zhanga6b1d892017-02-21 14:26:23 -0800278 target,
279 // TODO(carl-mastrangelo): Allow clients to pass this in
280 new ExponentialBackoffPolicy.Provider(),
281 nameResolverFactory,
282 getNameResolverParams(),
Kun Zhanga9bd9472017-02-21 17:11:03 -0800283 firstNonNull(loadBalancerFactory, PickFirstBalancerFactory.getInstance()),
Kun Zhanga6b1d892017-02-21 14:26:23 -0800284 transportFactory,
285 firstNonNull(decompressorRegistry, DecompressorRegistry.getDefaultInstance()),
286 firstNonNull(compressorRegistry, CompressorRegistry.getDefaultInstance()),
287 SharedResourcePool.forResource(GrpcUtil.TIMER_SERVICE),
288 getExecutorPool(executor),
289 SharedResourcePool.forResource(GrpcUtil.SHARED_CHANNEL_EXECUTOR),
Kun Zhanga9bd9472017-02-21 17:11:03 -0800290 GrpcUtil.STOPWATCH_SUPPLIER,
291 idleTimeoutMillis,
292 userAgent,
293 interceptors,
294 firstNonNull(
295 statsFactory,
Kun Zhanga6b1d892017-02-21 14:26:23 -0800296 firstNonNull(Stats.getStatsContextFactory(), NoopStatsContextFactory.INSTANCE)));
zhangkun8d6d12e2014-10-15 13:04:19 -0700297 }
298
299 /**
Kun Zhangedd57c92015-10-27 12:47:29 -0700300 * Subclasses should override this method to provide the {@link ClientTransportFactory}
301 * appropriate for this channel. This method is meant for Transport implementors and should not
302 * be used by normal users.
zhangkun8d6d12e2014-10-15 13:04:19 -0700303 */
nmittler777e9282015-08-19 10:01:52 -0700304 protected abstract ClientTransportFactory buildTransportFactory();
Kun Zhang942f4c92015-09-04 17:21:44 -0700305
Kun Zhangedd57c92015-10-27 12:47:29 -0700306 /**
307 * Subclasses can override this method to provide additional parameters to {@link
308 * NameResolver.Factory#newNameResolver}. The default implementation returns {@link
Carl Mastrangelo82a79d82015-12-07 14:40:11 -0800309 * Attributes#EMPTY}.
Kun Zhangedd57c92015-10-27 12:47:29 -0700310 */
311 protected Attributes getNameResolverParams() {
312 return Attributes.EMPTY;
313 }
314
Kun Zhangd17a7b52017-01-10 15:30:12 -0800315 private static ObjectPool<? extends Executor> getExecutorPool(final @Nullable Executor executor) {
316 if (executor != null) {
317 return new ObjectPool<Executor>() {
318 @Override
319 public Executor getObject() {
320 return executor;
321 }
322
323 @Override
324 public Executor returnObject(Object returned) {
325 return null;
326 }
327 };
328 } else {
329 return SharedResourcePool.forResource(GrpcUtil.SHARED_CHANNEL_EXECUTOR);
330 }
331 }
332
Kun Zhang942f4c92015-09-04 17:21:44 -0700333 private static class AuthorityOverridingTransportFactory implements ClientTransportFactory {
334 final ClientTransportFactory factory;
Sky Ao1d8aefa2016-04-18 23:43:30 +0800335 final String authorityOverride;
Kun Zhang942f4c92015-09-04 17:21:44 -0700336
337 AuthorityOverridingTransportFactory(
Sky Ao1d8aefa2016-04-18 23:43:30 +0800338 ClientTransportFactory factory, String authorityOverride) {
339 this.factory = Preconditions.checkNotNull(factory, "factory should not be null");
340 this.authorityOverride = Preconditions.checkNotNull(
341 authorityOverride, "authorityOverride should not be null");
Kun Zhang942f4c92015-09-04 17:21:44 -0700342 }
343
344 @Override
Kun Zhang432cec72016-05-29 14:43:10 -0700345 public ConnectionClientTransport newClientTransport(SocketAddress serverAddress,
Carl Mastrangelo1cc76d82016-05-24 16:29:26 -0700346 String authority, @Nullable String userAgent) {
347 return factory.newClientTransport(serverAddress, authorityOverride, userAgent);
Kun Zhang942f4c92015-09-04 17:21:44 -0700348 }
349
350 @Override
buchgr3c68c052016-03-17 00:14:43 +0100351 public void close() {
352 factory.close();
Kun Zhang942f4c92015-09-04 17:21:44 -0700353 }
354 }
355
356 private static class DirectAddressNameResolverFactory extends NameResolver.Factory {
357 final SocketAddress address;
358 final String authority;
359
360 DirectAddressNameResolverFactory(SocketAddress address, String authority) {
361 this.address = address;
362 this.authority = authority;
363 }
364
365 @Override
Kun Zhangedd57c92015-10-27 12:47:29 -0700366 public NameResolver newNameResolver(URI notUsedUri, Attributes params) {
Kun Zhang942f4c92015-09-04 17:21:44 -0700367 return new NameResolver() {
368 @Override
369 public String getServiceAuthority() {
370 return authority;
371 }
372
373 @Override
374 public void start(final Listener listener) {
Kun Zhang418d52d2017-03-22 18:29:31 -0700375 listener.onAddresses(
376 Collections.singletonList(new EquivalentAddressGroup(address)),
Kun Zhang942f4c92015-09-04 17:21:44 -0700377 Attributes.EMPTY);
378 }
379
380 @Override
381 public void shutdown() {}
382 };
383 }
Kun Zhang16247152015-12-08 17:52:05 -0800384
385 @Override
386 public String getDefaultScheme() {
387 return DIRECT_ADDRESS_SCHEME;
388 }
Kun Zhang942f4c92015-09-04 17:21:44 -0700389 }
Carl Mastrangelo84934982017-01-11 12:46:47 -0800390
391 /**
392 * Returns the correctly typed version of the builder.
393 */
394 private T thisT() {
395 @SuppressWarnings("unchecked")
396 T thisT = (T) this;
397 return thisT;
398 }
zhangkun8d6d12e2014-10-15 13:04:19 -0700399}