diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index d68d85eb0cd..8c934f24f3e 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -79,14 +79,9 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - include: - # Test with and without bzlmod. Bazel 6 doesn't support bzlmod, so use Bazel 7 instead - - bazel: 6.0.0 - bzlmod: false - - bazel: 7.0.0 - bzlmod: true + bzlmod: [true, false] env: - USE_BAZEL_VERSION: ${{ matrix.bazel }} + USE_BAZEL_VERSION: 7.0.0 steps: - uses: actions/checkout@v4 diff --git a/MODULE.bazel b/MODULE.bazel index edb5284a23d..4c7e1b3dca5 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -2,7 +2,7 @@ module( name = "grpc-java", compatibility_level = 0, repo_name = "io_grpc_grpc_java", - version = "1.70.0-SNAPSHOT", # CURRENT_GRPC_VERSION + version = "1.71.0-SNAPSHOT", # CURRENT_GRPC_VERSION ) # GRPC_DEPS_START diff --git a/README.md b/README.md index 97b2bd6d5f9..c6a8f3bdd8a 100644 --- a/README.md +++ b/README.md @@ -44,8 +44,8 @@ For a guided tour, take a look at the [quick start guide](https://grpc.io/docs/languages/java/quickstart) or the more explanatory [gRPC basics](https://grpc.io/docs/languages/java/basics). -The [examples](https://github.com/grpc/grpc-java/tree/v1.68.1/examples) and the -[Android example](https://github.com/grpc/grpc-java/tree/v1.68.1/examples/android) +The [examples](https://github.com/grpc/grpc-java/tree/v1.69.0/examples) and the +[Android example](https://github.com/grpc/grpc-java/tree/v1.69.0/examples/android) are standalone projects that showcase the usage of gRPC. Download @@ -56,18 +56,18 @@ Download [the JARs][]. Or for Maven with non-Android, add to your `pom.xml`: io.grpc grpc-netty-shaded - 1.68.1 + 1.69.0 runtime io.grpc grpc-protobuf - 1.68.1 + 1.69.0 io.grpc grpc-stub - 1.68.1 + 1.69.0 org.apache.tomcat @@ -79,18 +79,18 @@ Download [the JARs][]. Or for Maven with non-Android, add to your `pom.xml`: Or for Gradle with non-Android, add to your dependencies: ```gradle -runtimeOnly 'io.grpc:grpc-netty-shaded:1.68.1' -implementation 'io.grpc:grpc-protobuf:1.68.1' -implementation 'io.grpc:grpc-stub:1.68.1' +runtimeOnly 'io.grpc:grpc-netty-shaded:1.69.0' +implementation 'io.grpc:grpc-protobuf:1.69.0' +implementation 'io.grpc:grpc-stub:1.69.0' compileOnly 'org.apache.tomcat:annotations-api:6.0.53' // necessary for Java 9+ ``` For Android client, use `grpc-okhttp` instead of `grpc-netty-shaded` and `grpc-protobuf-lite` instead of `grpc-protobuf`: ```gradle -implementation 'io.grpc:grpc-okhttp:1.68.1' -implementation 'io.grpc:grpc-protobuf-lite:1.68.1' -implementation 'io.grpc:grpc-stub:1.68.1' +implementation 'io.grpc:grpc-okhttp:1.69.0' +implementation 'io.grpc:grpc-protobuf-lite:1.69.0' +implementation 'io.grpc:grpc-stub:1.69.0' compileOnly 'org.apache.tomcat:annotations-api:6.0.53' // necessary for Java 9+ ``` @@ -99,7 +99,7 @@ For [Bazel](https://bazel.build), you can either (with the GAVs from above), or use `@io_grpc_grpc_java//api` et al (see below). [the JARs]: -https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.68.1 +https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.69.0 Development snapshots are available in [Sonatypes's snapshot repository](https://oss.sonatype.org/content/repositories/snapshots/). @@ -131,7 +131,7 @@ For protobuf-based codegen integrated with the Maven build system, you can use com.google.protobuf:protoc:3.25.5:exe:${os.detected.classifier} grpc-java - io.grpc:protoc-gen-grpc-java:1.68.1:exe:${os.detected.classifier} + io.grpc:protoc-gen-grpc-java:1.69.0:exe:${os.detected.classifier} @@ -161,7 +161,7 @@ protobuf { } plugins { grpc { - artifact = 'io.grpc:protoc-gen-grpc-java:1.68.1' + artifact = 'io.grpc:protoc-gen-grpc-java:1.69.0' } } generateProtoTasks { @@ -194,7 +194,7 @@ protobuf { } plugins { grpc { - artifact = 'io.grpc:protoc-gen-grpc-java:1.68.1' + artifact = 'io.grpc:protoc-gen-grpc-java:1.69.0' } } generateProtoTasks { diff --git a/alts/BUILD.bazel b/alts/BUILD.bazel index 73420e11053..3595064ffa4 100644 --- a/alts/BUILD.bazel +++ b/alts/BUILD.bazel @@ -18,6 +18,7 @@ java_library( "@com_google_protobuf//:protobuf_java", "@com_google_protobuf//:protobuf_java_util", artifact("com.google.code.findbugs:jsr305"), + artifact("com.google.errorprone:error_prone_annotations"), artifact("com.google.guava:guava"), artifact("io.netty:netty-buffer"), artifact("io.netty:netty-codec"), diff --git a/alts/build.gradle b/alts/build.gradle index de93c90546f..3e472d9cea6 100644 --- a/alts/build.gradle +++ b/alts/build.gradle @@ -44,7 +44,11 @@ dependencies { classifier = "linux-x86_64" } } - signature libraries.signature.java + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } } configureProtoCompilation() diff --git a/alts/src/generated/main/grpc/io/grpc/alts/internal/HandshakerServiceGrpc.java b/alts/src/generated/main/grpc/io/grpc/alts/internal/HandshakerServiceGrpc.java index 2caba4a0544..91e88f331d7 100644 --- a/alts/src/generated/main/grpc/io/grpc/alts/internal/HandshakerServiceGrpc.java +++ b/alts/src/generated/main/grpc/io/grpc/alts/internal/HandshakerServiceGrpc.java @@ -60,6 +60,21 @@ public HandshakerServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOption return HandshakerServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static HandshakerServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public HandshakerServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new HandshakerServiceBlockingV2Stub(channel, callOptions); + } + }; + return HandshakerServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -157,6 +172,40 @@ public io.grpc.stub.StreamObserver doHandsh /** * A stub to allow clients to do synchronous rpc calls to service HandshakerService. */ + public static final class HandshakerServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private HandshakerServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected HandshakerServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new HandshakerServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * Handshaker service accepts a stream of handshaker request, returning a
+     * stream of handshaker response. Client is expected to send exactly one
+     * message with either client_start or server_start followed by one or more
+     * messages with next. Each time client sends a request, the handshaker
+     * service expects to respond. Client does not have to wait for service's
+     * response before sending next request.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + doHandshake() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getDoHandshakeMethod(), getCallOptions()); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service HandshakerService. + */ public static final class HandshakerServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private HandshakerServiceBlockingStub( diff --git a/alts/src/main/java/io/grpc/alts/internal/AsyncSemaphore.java b/alts/src/main/java/io/grpc/alts/internal/AsyncSemaphore.java index 3ccdcfc763a..a8251c7fbd3 100644 --- a/alts/src/main/java/io/grpc/alts/internal/AsyncSemaphore.java +++ b/alts/src/main/java/io/grpc/alts/internal/AsyncSemaphore.java @@ -16,12 +16,12 @@ package io.grpc.alts.internal; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPromise; import java.util.LinkedList; import java.util.Queue; -import javax.annotation.concurrent.GuardedBy; /** Provides a semaphore primitive, without blocking waiting on permits. */ final class AsyncSemaphore { diff --git a/android-interop-testing/build.gradle b/android-interop-testing/build.gradle index 9b3b021afce..1d39aee1750 100644 --- a/android-interop-testing/build.gradle +++ b/android-interop-testing/build.gradle @@ -7,7 +7,6 @@ description = 'gRPC: Android Integration Testing' repositories { google() - mavenCentral() } android { diff --git a/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/LoadBalancerStatsServiceGrpc.java b/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/LoadBalancerStatsServiceGrpc.java index e030fde13e3..120033a8051 100644 --- a/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/LoadBalancerStatsServiceGrpc.java +++ b/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/LoadBalancerStatsServiceGrpc.java @@ -92,6 +92,21 @@ public LoadBalancerStatsServiceStub newStub(io.grpc.Channel channel, io.grpc.Cal return LoadBalancerStatsServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static LoadBalancerStatsServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public LoadBalancerStatsServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new LoadBalancerStatsServiceBlockingV2Stub(channel, callOptions); + } + }; + return LoadBalancerStatsServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -212,6 +227,46 @@ public void getClientAccumulatedStats(io.grpc.testing.integration.Messages.LoadB * A service used to obtain stats for verifying LB behavior. * */ + public static final class LoadBalancerStatsServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private LoadBalancerStatsServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected LoadBalancerStatsServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new LoadBalancerStatsServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * Gets the backend distribution for RPCs sent by a test client.
+     * 
+ */ + public io.grpc.testing.integration.Messages.LoadBalancerStatsResponse getClientStats(io.grpc.testing.integration.Messages.LoadBalancerStatsRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getGetClientStatsMethod(), getCallOptions(), request); + } + + /** + *
+     * Gets the accumulated stats for RPCs sent by a test client.
+     * 
+ */ + public io.grpc.testing.integration.Messages.LoadBalancerAccumulatedStatsResponse getClientAccumulatedStats(io.grpc.testing.integration.Messages.LoadBalancerAccumulatedStatsRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getGetClientAccumulatedStatsMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service LoadBalancerStatsService. + *
+   * A service used to obtain stats for verifying LB behavior.
+   * 
+ */ public static final class LoadBalancerStatsServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private LoadBalancerStatsServiceBlockingStub( diff --git a/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/MetricsServiceGrpc.java b/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/MetricsServiceGrpc.java index e8726d5adc4..489838ddc6c 100644 --- a/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/MetricsServiceGrpc.java +++ b/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/MetricsServiceGrpc.java @@ -89,6 +89,21 @@ public MetricsServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions c return MetricsServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static MetricsServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public MetricsServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new MetricsServiceBlockingV2Stub(channel, callOptions); + } + }; + return MetricsServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -199,6 +214,46 @@ public void getGauge(io.grpc.testing.integration.Metrics.GaugeRequest request, /** * A stub to allow clients to do synchronous rpc calls to service MetricsService. */ + public static final class MetricsServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private MetricsServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected MetricsServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new MetricsServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * Returns the values of all the gauges that are currently being maintained by
+     * the service
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + getAllGauges(io.grpc.testing.integration.Metrics.EmptyMessage request) { + return io.grpc.stub.ClientCalls.blockingV2ServerStreamingCall( + getChannel(), getGetAllGaugesMethod(), getCallOptions(), request); + } + + /** + *
+     * Returns the value of one gauge
+     * 
+ */ + public io.grpc.testing.integration.Metrics.GaugeResponse getGauge(io.grpc.testing.integration.Metrics.GaugeRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getGetGaugeMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service MetricsService. + */ public static final class MetricsServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private MetricsServiceBlockingStub( diff --git a/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/ReconnectServiceGrpc.java b/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/ReconnectServiceGrpc.java index 8ede6407cd0..e0ea29e42e7 100644 --- a/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/ReconnectServiceGrpc.java +++ b/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/ReconnectServiceGrpc.java @@ -92,6 +92,21 @@ public ReconnectServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions return ReconnectServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static ReconnectServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public ReconnectServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new ReconnectServiceBlockingV2Stub(channel, callOptions); + } + }; + return ReconnectServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -200,6 +215,40 @@ public void stop(io.grpc.testing.integration.EmptyProtos.Empty request, * A service used to control reconnect server. * */ + public static final class ReconnectServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private ReconnectServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected ReconnectServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new ReconnectServiceBlockingV2Stub(channel, callOptions); + } + + /** + */ + public io.grpc.testing.integration.EmptyProtos.Empty start(io.grpc.testing.integration.Messages.ReconnectParams request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getStartMethod(), getCallOptions(), request); + } + + /** + */ + public io.grpc.testing.integration.Messages.ReconnectInfo stop(io.grpc.testing.integration.EmptyProtos.Empty request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getStopMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service ReconnectService. + *
+   * A service used to control reconnect server.
+   * 
+ */ public static final class ReconnectServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private ReconnectServiceBlockingStub( diff --git a/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/TestServiceGrpc.java b/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/TestServiceGrpc.java index 01e2678a12f..a0f44f46473 100644 --- a/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/TestServiceGrpc.java +++ b/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/TestServiceGrpc.java @@ -273,6 +273,21 @@ public TestServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions call return TestServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static TestServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public TestServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new TestServiceBlockingV2Stub(channel, callOptions); + } + }; + return TestServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -543,6 +558,125 @@ public void unimplementedCall(io.grpc.testing.integration.EmptyProtos.Empty requ * performance with various types of payload. * */ + public static final class TestServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private TestServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected TestServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new TestServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * One empty request followed by one empty response.
+     * 
+ */ + public io.grpc.testing.integration.EmptyProtos.Empty emptyCall(io.grpc.testing.integration.EmptyProtos.Empty request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getEmptyCallMethod(), getCallOptions(), request); + } + + /** + *
+     * One request followed by one response.
+     * 
+ */ + public io.grpc.testing.integration.Messages.SimpleResponse unaryCall(io.grpc.testing.integration.Messages.SimpleRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getUnaryCallMethod(), getCallOptions(), request); + } + + /** + *
+     * One request followed by one response. Response has cache control
+     * headers set such that a caching HTTP proxy (such as GFE) can
+     * satisfy subsequent requests.
+     * 
+ */ + public io.grpc.testing.integration.Messages.SimpleResponse cacheableUnaryCall(io.grpc.testing.integration.Messages.SimpleRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getCacheableUnaryCallMethod(), getCallOptions(), request); + } + + /** + *
+     * One request followed by a sequence of responses (streamed download).
+     * The server returns the payload with client desired type and sizes.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + streamingOutputCall(io.grpc.testing.integration.Messages.StreamingOutputCallRequest request) { + return io.grpc.stub.ClientCalls.blockingV2ServerStreamingCall( + getChannel(), getStreamingOutputCallMethod(), getCallOptions(), request); + } + + /** + *
+     * A sequence of requests followed by one response (streamed upload).
+     * The server returns the aggregated size of client payload as the result.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + streamingInputCall() { + return io.grpc.stub.ClientCalls.blockingClientStreamingCall( + getChannel(), getStreamingInputCallMethod(), getCallOptions()); + } + + /** + *
+     * A sequence of requests with each request served by the server immediately.
+     * As one request could lead to multiple responses, this interface
+     * demonstrates the idea of full duplexing.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + fullDuplexCall() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getFullDuplexCallMethod(), getCallOptions()); + } + + /** + *
+     * A sequence of requests followed by a sequence of responses.
+     * The server buffers all the client requests and then serves them in order. A
+     * stream of responses are returned to the client when the server starts with
+     * first request.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + halfDuplexCall() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getHalfDuplexCallMethod(), getCallOptions()); + } + + /** + *
+     * The test server will not implement this method. It will be used
+     * to test the behavior when clients call unimplemented methods.
+     * 
+ */ + public io.grpc.testing.integration.EmptyProtos.Empty unimplementedCall(io.grpc.testing.integration.EmptyProtos.Empty request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getUnimplementedCallMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service TestService. + *
+   * A simple service to test the various types of RPCs and experiment with
+   * performance with various types of payload.
+   * 
+ */ public static final class TestServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private TestServiceBlockingStub( diff --git a/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/UnimplementedServiceGrpc.java b/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/UnimplementedServiceGrpc.java index 743d68c3828..f758c2d0840 100644 --- a/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/UnimplementedServiceGrpc.java +++ b/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/UnimplementedServiceGrpc.java @@ -63,6 +63,21 @@ public UnimplementedServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOpt return UnimplementedServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static UnimplementedServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public UnimplementedServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new UnimplementedServiceBlockingV2Stub(channel, callOptions); + } + }; + return UnimplementedServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -166,6 +181,37 @@ public void unimplementedCall(io.grpc.testing.integration.EmptyProtos.Empty requ * that case. * */ + public static final class UnimplementedServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private UnimplementedServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected UnimplementedServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new UnimplementedServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * A call that no server should implement
+     * 
+ */ + public io.grpc.testing.integration.EmptyProtos.Empty unimplementedCall(io.grpc.testing.integration.EmptyProtos.Empty request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getUnimplementedCallMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service UnimplementedService. + *
+   * A simple service NOT implemented at servers so clients can test for
+   * that case.
+   * 
+ */ public static final class UnimplementedServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private UnimplementedServiceBlockingStub( diff --git a/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/XdsUpdateClientConfigureServiceGrpc.java b/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/XdsUpdateClientConfigureServiceGrpc.java index 61cfc19d29b..5fa43e4721a 100644 --- a/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/XdsUpdateClientConfigureServiceGrpc.java +++ b/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/XdsUpdateClientConfigureServiceGrpc.java @@ -62,6 +62,21 @@ public XdsUpdateClientConfigureServiceStub newStub(io.grpc.Channel channel, io.g return XdsUpdateClientConfigureServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static XdsUpdateClientConfigureServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public XdsUpdateClientConfigureServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new XdsUpdateClientConfigureServiceBlockingV2Stub(channel, callOptions); + } + }; + return XdsUpdateClientConfigureServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -161,6 +176,36 @@ public void configure(io.grpc.testing.integration.Messages.ClientConfigureReques * A service to dynamically update the configuration of an xDS test client. * */ + public static final class XdsUpdateClientConfigureServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private XdsUpdateClientConfigureServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected XdsUpdateClientConfigureServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new XdsUpdateClientConfigureServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * Update the tes client's configuration.
+     * 
+ */ + public io.grpc.testing.integration.Messages.ClientConfigureResponse configure(io.grpc.testing.integration.Messages.ClientConfigureRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getConfigureMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service XdsUpdateClientConfigureService. + *
+   * A service to dynamically update the configuration of an xDS test client.
+   * 
+ */ public static final class XdsUpdateClientConfigureServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private XdsUpdateClientConfigureServiceBlockingStub( diff --git a/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/XdsUpdateHealthServiceGrpc.java b/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/XdsUpdateHealthServiceGrpc.java index 6ba9419dedf..2492ec0f90b 100644 --- a/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/XdsUpdateHealthServiceGrpc.java +++ b/android-interop-testing/src/generated/debug/grpc/io/grpc/testing/integration/XdsUpdateHealthServiceGrpc.java @@ -92,6 +92,21 @@ public XdsUpdateHealthServiceStub newStub(io.grpc.Channel channel, io.grpc.CallO return XdsUpdateHealthServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static XdsUpdateHealthServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public XdsUpdateHealthServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new XdsUpdateHealthServiceBlockingV2Stub(channel, callOptions); + } + }; + return XdsUpdateHealthServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -200,6 +215,40 @@ public void setNotServing(io.grpc.testing.integration.EmptyProtos.Empty request, * A service to remotely control health status of an xDS test server. * */ + public static final class XdsUpdateHealthServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private XdsUpdateHealthServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected XdsUpdateHealthServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new XdsUpdateHealthServiceBlockingV2Stub(channel, callOptions); + } + + /** + */ + public io.grpc.testing.integration.EmptyProtos.Empty setServing(io.grpc.testing.integration.EmptyProtos.Empty request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getSetServingMethod(), getCallOptions(), request); + } + + /** + */ + public io.grpc.testing.integration.EmptyProtos.Empty setNotServing(io.grpc.testing.integration.EmptyProtos.Empty request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getSetNotServingMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service XdsUpdateHealthService. + *
+   * A service to remotely control health status of an xDS test server.
+   * 
+ */ public static final class XdsUpdateHealthServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private XdsUpdateHealthServiceBlockingStub( diff --git a/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/LoadBalancerStatsServiceGrpc.java b/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/LoadBalancerStatsServiceGrpc.java index e030fde13e3..120033a8051 100644 --- a/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/LoadBalancerStatsServiceGrpc.java +++ b/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/LoadBalancerStatsServiceGrpc.java @@ -92,6 +92,21 @@ public LoadBalancerStatsServiceStub newStub(io.grpc.Channel channel, io.grpc.Cal return LoadBalancerStatsServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static LoadBalancerStatsServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public LoadBalancerStatsServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new LoadBalancerStatsServiceBlockingV2Stub(channel, callOptions); + } + }; + return LoadBalancerStatsServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -212,6 +227,46 @@ public void getClientAccumulatedStats(io.grpc.testing.integration.Messages.LoadB * A service used to obtain stats for verifying LB behavior. * */ + public static final class LoadBalancerStatsServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private LoadBalancerStatsServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected LoadBalancerStatsServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new LoadBalancerStatsServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * Gets the backend distribution for RPCs sent by a test client.
+     * 
+ */ + public io.grpc.testing.integration.Messages.LoadBalancerStatsResponse getClientStats(io.grpc.testing.integration.Messages.LoadBalancerStatsRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getGetClientStatsMethod(), getCallOptions(), request); + } + + /** + *
+     * Gets the accumulated stats for RPCs sent by a test client.
+     * 
+ */ + public io.grpc.testing.integration.Messages.LoadBalancerAccumulatedStatsResponse getClientAccumulatedStats(io.grpc.testing.integration.Messages.LoadBalancerAccumulatedStatsRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getGetClientAccumulatedStatsMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service LoadBalancerStatsService. + *
+   * A service used to obtain stats for verifying LB behavior.
+   * 
+ */ public static final class LoadBalancerStatsServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private LoadBalancerStatsServiceBlockingStub( diff --git a/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/MetricsServiceGrpc.java b/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/MetricsServiceGrpc.java index e8726d5adc4..489838ddc6c 100644 --- a/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/MetricsServiceGrpc.java +++ b/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/MetricsServiceGrpc.java @@ -89,6 +89,21 @@ public MetricsServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions c return MetricsServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static MetricsServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public MetricsServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new MetricsServiceBlockingV2Stub(channel, callOptions); + } + }; + return MetricsServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -199,6 +214,46 @@ public void getGauge(io.grpc.testing.integration.Metrics.GaugeRequest request, /** * A stub to allow clients to do synchronous rpc calls to service MetricsService. */ + public static final class MetricsServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private MetricsServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected MetricsServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new MetricsServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * Returns the values of all the gauges that are currently being maintained by
+     * the service
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + getAllGauges(io.grpc.testing.integration.Metrics.EmptyMessage request) { + return io.grpc.stub.ClientCalls.blockingV2ServerStreamingCall( + getChannel(), getGetAllGaugesMethod(), getCallOptions(), request); + } + + /** + *
+     * Returns the value of one gauge
+     * 
+ */ + public io.grpc.testing.integration.Metrics.GaugeResponse getGauge(io.grpc.testing.integration.Metrics.GaugeRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getGetGaugeMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service MetricsService. + */ public static final class MetricsServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private MetricsServiceBlockingStub( diff --git a/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/ReconnectServiceGrpc.java b/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/ReconnectServiceGrpc.java index 8ede6407cd0..e0ea29e42e7 100644 --- a/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/ReconnectServiceGrpc.java +++ b/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/ReconnectServiceGrpc.java @@ -92,6 +92,21 @@ public ReconnectServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions return ReconnectServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static ReconnectServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public ReconnectServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new ReconnectServiceBlockingV2Stub(channel, callOptions); + } + }; + return ReconnectServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -200,6 +215,40 @@ public void stop(io.grpc.testing.integration.EmptyProtos.Empty request, * A service used to control reconnect server. * */ + public static final class ReconnectServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private ReconnectServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected ReconnectServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new ReconnectServiceBlockingV2Stub(channel, callOptions); + } + + /** + */ + public io.grpc.testing.integration.EmptyProtos.Empty start(io.grpc.testing.integration.Messages.ReconnectParams request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getStartMethod(), getCallOptions(), request); + } + + /** + */ + public io.grpc.testing.integration.Messages.ReconnectInfo stop(io.grpc.testing.integration.EmptyProtos.Empty request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getStopMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service ReconnectService. + *
+   * A service used to control reconnect server.
+   * 
+ */ public static final class ReconnectServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private ReconnectServiceBlockingStub( diff --git a/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/TestServiceGrpc.java b/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/TestServiceGrpc.java index 01e2678a12f..a0f44f46473 100644 --- a/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/TestServiceGrpc.java +++ b/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/TestServiceGrpc.java @@ -273,6 +273,21 @@ public TestServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions call return TestServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static TestServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public TestServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new TestServiceBlockingV2Stub(channel, callOptions); + } + }; + return TestServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -543,6 +558,125 @@ public void unimplementedCall(io.grpc.testing.integration.EmptyProtos.Empty requ * performance with various types of payload. * */ + public static final class TestServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private TestServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected TestServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new TestServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * One empty request followed by one empty response.
+     * 
+ */ + public io.grpc.testing.integration.EmptyProtos.Empty emptyCall(io.grpc.testing.integration.EmptyProtos.Empty request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getEmptyCallMethod(), getCallOptions(), request); + } + + /** + *
+     * One request followed by one response.
+     * 
+ */ + public io.grpc.testing.integration.Messages.SimpleResponse unaryCall(io.grpc.testing.integration.Messages.SimpleRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getUnaryCallMethod(), getCallOptions(), request); + } + + /** + *
+     * One request followed by one response. Response has cache control
+     * headers set such that a caching HTTP proxy (such as GFE) can
+     * satisfy subsequent requests.
+     * 
+ */ + public io.grpc.testing.integration.Messages.SimpleResponse cacheableUnaryCall(io.grpc.testing.integration.Messages.SimpleRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getCacheableUnaryCallMethod(), getCallOptions(), request); + } + + /** + *
+     * One request followed by a sequence of responses (streamed download).
+     * The server returns the payload with client desired type and sizes.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + streamingOutputCall(io.grpc.testing.integration.Messages.StreamingOutputCallRequest request) { + return io.grpc.stub.ClientCalls.blockingV2ServerStreamingCall( + getChannel(), getStreamingOutputCallMethod(), getCallOptions(), request); + } + + /** + *
+     * A sequence of requests followed by one response (streamed upload).
+     * The server returns the aggregated size of client payload as the result.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + streamingInputCall() { + return io.grpc.stub.ClientCalls.blockingClientStreamingCall( + getChannel(), getStreamingInputCallMethod(), getCallOptions()); + } + + /** + *
+     * A sequence of requests with each request served by the server immediately.
+     * As one request could lead to multiple responses, this interface
+     * demonstrates the idea of full duplexing.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + fullDuplexCall() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getFullDuplexCallMethod(), getCallOptions()); + } + + /** + *
+     * A sequence of requests followed by a sequence of responses.
+     * The server buffers all the client requests and then serves them in order. A
+     * stream of responses are returned to the client when the server starts with
+     * first request.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + halfDuplexCall() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getHalfDuplexCallMethod(), getCallOptions()); + } + + /** + *
+     * The test server will not implement this method. It will be used
+     * to test the behavior when clients call unimplemented methods.
+     * 
+ */ + public io.grpc.testing.integration.EmptyProtos.Empty unimplementedCall(io.grpc.testing.integration.EmptyProtos.Empty request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getUnimplementedCallMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service TestService. + *
+   * A simple service to test the various types of RPCs and experiment with
+   * performance with various types of payload.
+   * 
+ */ public static final class TestServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private TestServiceBlockingStub( diff --git a/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/UnimplementedServiceGrpc.java b/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/UnimplementedServiceGrpc.java index 743d68c3828..f758c2d0840 100644 --- a/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/UnimplementedServiceGrpc.java +++ b/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/UnimplementedServiceGrpc.java @@ -63,6 +63,21 @@ public UnimplementedServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOpt return UnimplementedServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static UnimplementedServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public UnimplementedServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new UnimplementedServiceBlockingV2Stub(channel, callOptions); + } + }; + return UnimplementedServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -166,6 +181,37 @@ public void unimplementedCall(io.grpc.testing.integration.EmptyProtos.Empty requ * that case. * */ + public static final class UnimplementedServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private UnimplementedServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected UnimplementedServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new UnimplementedServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * A call that no server should implement
+     * 
+ */ + public io.grpc.testing.integration.EmptyProtos.Empty unimplementedCall(io.grpc.testing.integration.EmptyProtos.Empty request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getUnimplementedCallMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service UnimplementedService. + *
+   * A simple service NOT implemented at servers so clients can test for
+   * that case.
+   * 
+ */ public static final class UnimplementedServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private UnimplementedServiceBlockingStub( diff --git a/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/XdsUpdateClientConfigureServiceGrpc.java b/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/XdsUpdateClientConfigureServiceGrpc.java index 61cfc19d29b..5fa43e4721a 100644 --- a/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/XdsUpdateClientConfigureServiceGrpc.java +++ b/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/XdsUpdateClientConfigureServiceGrpc.java @@ -62,6 +62,21 @@ public XdsUpdateClientConfigureServiceStub newStub(io.grpc.Channel channel, io.g return XdsUpdateClientConfigureServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static XdsUpdateClientConfigureServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public XdsUpdateClientConfigureServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new XdsUpdateClientConfigureServiceBlockingV2Stub(channel, callOptions); + } + }; + return XdsUpdateClientConfigureServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -161,6 +176,36 @@ public void configure(io.grpc.testing.integration.Messages.ClientConfigureReques * A service to dynamically update the configuration of an xDS test client. * */ + public static final class XdsUpdateClientConfigureServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private XdsUpdateClientConfigureServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected XdsUpdateClientConfigureServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new XdsUpdateClientConfigureServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * Update the tes client's configuration.
+     * 
+ */ + public io.grpc.testing.integration.Messages.ClientConfigureResponse configure(io.grpc.testing.integration.Messages.ClientConfigureRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getConfigureMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service XdsUpdateClientConfigureService. + *
+   * A service to dynamically update the configuration of an xDS test client.
+   * 
+ */ public static final class XdsUpdateClientConfigureServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private XdsUpdateClientConfigureServiceBlockingStub( diff --git a/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/XdsUpdateHealthServiceGrpc.java b/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/XdsUpdateHealthServiceGrpc.java index 6ba9419dedf..2492ec0f90b 100644 --- a/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/XdsUpdateHealthServiceGrpc.java +++ b/android-interop-testing/src/generated/release/grpc/io/grpc/testing/integration/XdsUpdateHealthServiceGrpc.java @@ -92,6 +92,21 @@ public XdsUpdateHealthServiceStub newStub(io.grpc.Channel channel, io.grpc.CallO return XdsUpdateHealthServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static XdsUpdateHealthServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public XdsUpdateHealthServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new XdsUpdateHealthServiceBlockingV2Stub(channel, callOptions); + } + }; + return XdsUpdateHealthServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -200,6 +215,40 @@ public void setNotServing(io.grpc.testing.integration.EmptyProtos.Empty request, * A service to remotely control health status of an xDS test server. * */ + public static final class XdsUpdateHealthServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private XdsUpdateHealthServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected XdsUpdateHealthServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new XdsUpdateHealthServiceBlockingV2Stub(channel, callOptions); + } + + /** + */ + public io.grpc.testing.integration.EmptyProtos.Empty setServing(io.grpc.testing.integration.EmptyProtos.Empty request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getSetServingMethod(), getCallOptions(), request); + } + + /** + */ + public io.grpc.testing.integration.EmptyProtos.Empty setNotServing(io.grpc.testing.integration.EmptyProtos.Empty request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getSetNotServingMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service XdsUpdateHealthService. + *
+   * A service to remotely control health status of an xDS test server.
+   * 
+ */ public static final class XdsUpdateHealthServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private XdsUpdateHealthServiceBlockingStub( diff --git a/android/build.gradle b/android/build.gradle index 3b3bfa59b96..3c717da18a3 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -31,7 +31,6 @@ android { repositories { google() - mavenCentral() } dependencies { diff --git a/android/src/main/java/io/grpc/android/AndroidChannelBuilder.java b/android/src/main/java/io/grpc/android/AndroidChannelBuilder.java index 317b7a50b74..e56ce5fc405 100644 --- a/android/src/main/java/io/grpc/android/AndroidChannelBuilder.java +++ b/android/src/main/java/io/grpc/android/AndroidChannelBuilder.java @@ -28,6 +28,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.errorprone.annotations.InlineMe; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.CallOptions; import io.grpc.ClientCall; import io.grpc.ConnectivityState; @@ -41,7 +42,6 @@ import io.grpc.internal.GrpcUtil; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; /** * Builds a {@link ManagedChannel} that, when provided with a {@link Context}, will automatically diff --git a/api/BUILD.bazel b/api/BUILD.bazel index 6bf3375e9f0..965d14a9eb0 100644 --- a/api/BUILD.bazel +++ b/api/BUILD.bazel @@ -6,7 +6,6 @@ java_library( "src/main/java/**/*.java", "src/context/java/**/*.java", ]), - javacopts = ["-Xep:DoNotCall:OFF"], # Remove once requiring Bazel 3.4.0+; allows non-final visibility = ["//visibility:public"], deps = [ artifact("com.google.code.findbugs:jsr305"), diff --git a/api/build.gradle b/api/build.gradle index 1d21c7bdcb6..dc3eaea3f4e 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -48,8 +48,20 @@ dependencies { testImplementation project(':grpc-testing') testImplementation libraries.guava.testlib - signature libraries.signature.java - signature libraries.signature.android + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } + signature (libraries.signature.android) { + artifact { + extension = "signature" + } + } +} + +animalsniffer { + annotation = 'io.grpc.IgnoreJRERequirement' } tasks.named("javadoc").configure { diff --git a/api/src/main/java/io/grpc/CallOptions.java b/api/src/main/java/io/grpc/CallOptions.java index a1b8984c48b..800bdfb6c90 100644 --- a/api/src/main/java/io/grpc/CallOptions.java +++ b/api/src/main/java/io/grpc/CallOptions.java @@ -21,6 +21,7 @@ import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; +import com.google.errorprone.annotations.CheckReturnValue; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; @@ -28,7 +29,6 @@ import java.util.List; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; -import javax.annotation.CheckReturnValue; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; diff --git a/api/src/main/java/io/grpc/ConfiguratorRegistry.java b/api/src/main/java/io/grpc/ConfiguratorRegistry.java index b2efcc1cff4..a0a91609dde 100644 --- a/api/src/main/java/io/grpc/ConfiguratorRegistry.java +++ b/api/src/main/java/io/grpc/ConfiguratorRegistry.java @@ -16,10 +16,10 @@ package io.grpc; +import com.google.errorprone.annotations.concurrent.GuardedBy; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import javax.annotation.concurrent.GuardedBy; /** * A registry for {@link Configurator} instances. diff --git a/api/src/main/java/io/grpc/ForwardingChannelBuilder2.java b/api/src/main/java/io/grpc/ForwardingChannelBuilder2.java index 7f21a57ec80..78fe730d91a 100644 --- a/api/src/main/java/io/grpc/ForwardingChannelBuilder2.java +++ b/api/src/main/java/io/grpc/ForwardingChannelBuilder2.java @@ -263,6 +263,12 @@ protected T addMetricSink(MetricSink metricSink) { return thisT(); } + @Override + public T setNameResolverArg(NameResolver.Args.Key key, X value) { + delegate().setNameResolverArg(key, value); + return thisT(); + } + /** * Returns the {@link ManagedChannel} built by the delegate by default. Overriding method can * return different value. diff --git a/api/src/main/java/io/grpc/IgnoreJRERequirement.java b/api/src/main/java/io/grpc/IgnoreJRERequirement.java new file mode 100644 index 00000000000..2db406c5953 --- /dev/null +++ b/api/src/main/java/io/grpc/IgnoreJRERequirement.java @@ -0,0 +1,30 @@ +/* + * Copyright 2024 The gRPC Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +/** + * Disables Animal Sniffer's signature checking. This is our own package-private version to avoid + * dependening on animalsniffer-annotations. + * + *

FIELD is purposefully not supported, as Android wouldn't be able to ignore a field. Instead, + * the entire class would need to be avoided on Android. + */ +@Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.TYPE}) +@interface IgnoreJRERequirement {} diff --git a/api/src/main/java/io/grpc/InternalStatus.java b/api/src/main/java/io/grpc/InternalStatus.java index b6549bb435f..56df1decf38 100644 --- a/api/src/main/java/io/grpc/InternalStatus.java +++ b/api/src/main/java/io/grpc/InternalStatus.java @@ -38,12 +38,11 @@ private InternalStatus() {} public static final Metadata.Key CODE_KEY = Status.CODE_KEY; /** - * Create a new {@link StatusRuntimeException} with the internal option of skipping the filling - * of the stack trace. + * Create a new {@link StatusRuntimeException} skipping the filling of the stack trace. */ @Internal - public static final StatusRuntimeException asRuntimeException(Status status, - @Nullable Metadata trailers, boolean fillInStackTrace) { - return new StatusRuntimeException(status, trailers, fillInStackTrace); + public static StatusRuntimeException asRuntimeExceptionWithoutStacktrace(Status status, + @Nullable Metadata trailers) { + return new InternalStatusRuntimeException(status, trailers); } } diff --git a/api/src/main/java/io/grpc/InternalStatusRuntimeException.java b/api/src/main/java/io/grpc/InternalStatusRuntimeException.java new file mode 100644 index 00000000000..6090b701f0b --- /dev/null +++ b/api/src/main/java/io/grpc/InternalStatusRuntimeException.java @@ -0,0 +1,39 @@ +/* + * Copyright 2015 The gRPC Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc; + +import javax.annotation.Nullable; + +/** + * StatusRuntimeException without stack trace, implemented as a subclass, as the + * {@code String, Throwable, boolean, boolean} constructor is not available in the supported + * version of Android. + * + * @see StatusRuntimeException + */ +class InternalStatusRuntimeException extends StatusRuntimeException { + private static final long serialVersionUID = 0; + + public InternalStatusRuntimeException(Status status, @Nullable Metadata trailers) { + super(status, trailers); + } + + @Override + public synchronized Throwable fillInStackTrace() { + return this; + } +} diff --git a/api/src/main/java/io/grpc/ManagedChannelBuilder.java b/api/src/main/java/io/grpc/ManagedChannelBuilder.java index 6e30d8eae04..df867d09ba1 100644 --- a/api/src/main/java/io/grpc/ManagedChannelBuilder.java +++ b/api/src/main/java/io/grpc/ManagedChannelBuilder.java @@ -633,6 +633,23 @@ protected T addMetricSink(MetricSink metricSink) { throw new UnsupportedOperationException(); } + /** + * Provides a "custom" argument for the {@link NameResolver}, if applicable, replacing any 'value' + * previously provided for 'key'. + * + *

NB: If the selected {@link NameResolver} does not understand 'key', or target URI resolution + * isn't needed at all, your custom argument will be silently ignored. + * + *

See {@link NameResolver.Args#getArg(NameResolver.Args.Key)} for more. + * + * @param key identifies the argument in a type-safe manner + * @param value the argument itself + * @return this + */ + @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1770") + public T setNameResolverArg(NameResolver.Args.Key key, X value) { + throw new UnsupportedOperationException(); + } /** * Builds a channel using the given parameters. diff --git a/api/src/main/java/io/grpc/ManagedChannelRegistry.java b/api/src/main/java/io/grpc/ManagedChannelRegistry.java index 3d0b1647bda..fc9e693b560 100644 --- a/api/src/main/java/io/grpc/ManagedChannelRegistry.java +++ b/api/src/main/java/io/grpc/ManagedChannelRegistry.java @@ -18,6 +18,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; +import com.google.errorprone.annotations.concurrent.GuardedBy; import java.net.SocketAddress; import java.net.URI; import java.net.URISyntaxException; @@ -30,7 +31,6 @@ import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.ThreadSafe; /** diff --git a/api/src/main/java/io/grpc/MethodDescriptor.java b/api/src/main/java/io/grpc/MethodDescriptor.java index 1bfaccb4201..a02eb840deb 100644 --- a/api/src/main/java/io/grpc/MethodDescriptor.java +++ b/api/src/main/java/io/grpc/MethodDescriptor.java @@ -20,9 +20,9 @@ import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; +import com.google.errorprone.annotations.CheckReturnValue; import java.io.InputStream; import java.util.concurrent.atomic.AtomicReferenceArray; -import javax.annotation.CheckReturnValue; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; diff --git a/api/src/main/java/io/grpc/MetricInstrumentRegistry.java b/api/src/main/java/io/grpc/MetricInstrumentRegistry.java index a61ac058a61..1b33ed17a71 100644 --- a/api/src/main/java/io/grpc/MetricInstrumentRegistry.java +++ b/api/src/main/java/io/grpc/MetricInstrumentRegistry.java @@ -21,12 +21,12 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; +import com.google.errorprone.annotations.concurrent.GuardedBy; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; -import javax.annotation.concurrent.GuardedBy; /** * A registry for globally registered metric instruments. diff --git a/api/src/main/java/io/grpc/NameResolver.java b/api/src/main/java/io/grpc/NameResolver.java index b35601289a3..e8295365ca8 100644 --- a/api/src/main/java/io/grpc/NameResolver.java +++ b/api/src/main/java/io/grpc/NameResolver.java @@ -28,11 +28,13 @@ import java.lang.annotation.RetentionPolicy; import java.net.URI; import java.util.Collections; +import java.util.IdentityHashMap; import java.util.List; import java.util.Map; import java.util.concurrent.Executor; import java.util.concurrent.ScheduledExecutorService; import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.ThreadSafe; /** @@ -276,7 +278,12 @@ public Status onResult2(ResolutionResult resolutionResult) { /** * Information that a {@link Factory} uses to create a {@link NameResolver}. * - *

Note this class doesn't override neither {@code equals()} nor {@code hashCode()}. + *

Args applicable to all {@link NameResolver}s are defined here using ordinary setters and + * getters. This container can also hold externally-defined "custom" args that aren't so widely + * useful or that would be inappropriate dependencies for this low level API. See {@link + * Args#getArg} for more. + * + *

Note this class overrides neither {@code equals()} nor {@code hashCode()}. * * @since 1.21.0 */ @@ -291,26 +298,20 @@ public static final class Args { @Nullable private final Executor executor; @Nullable private final String overrideAuthority; @Nullable private final MetricRecorder metricRecorder; + @Nullable private final IdentityHashMap, Object> customArgs; - private Args( - Integer defaultPort, - ProxyDetector proxyDetector, - SynchronizationContext syncContext, - ServiceConfigParser serviceConfigParser, - @Nullable ScheduledExecutorService scheduledExecutorService, - @Nullable ChannelLogger channelLogger, - @Nullable Executor executor, - @Nullable String overrideAuthority, - @Nullable MetricRecorder metricRecorder) { - this.defaultPort = checkNotNull(defaultPort, "defaultPort not set"); - this.proxyDetector = checkNotNull(proxyDetector, "proxyDetector not set"); - this.syncContext = checkNotNull(syncContext, "syncContext not set"); - this.serviceConfigParser = checkNotNull(serviceConfigParser, "serviceConfigParser not set"); - this.scheduledExecutorService = scheduledExecutorService; - this.channelLogger = channelLogger; - this.executor = executor; - this.overrideAuthority = overrideAuthority; - this.metricRecorder = metricRecorder; + private Args(Builder builder) { + this.defaultPort = checkNotNull(builder.defaultPort, "defaultPort not set"); + this.proxyDetector = checkNotNull(builder.proxyDetector, "proxyDetector not set"); + this.syncContext = checkNotNull(builder.syncContext, "syncContext not set"); + this.serviceConfigParser = + checkNotNull(builder.serviceConfigParser, "serviceConfigParser not set"); + this.scheduledExecutorService = builder.scheduledExecutorService; + this.channelLogger = builder.channelLogger; + this.executor = builder.executor; + this.overrideAuthority = builder.overrideAuthority; + this.metricRecorder = builder.metricRecorder; + this.customArgs = cloneCustomArgs(builder.customArgs); } /** @@ -319,6 +320,7 @@ private Args( * * @since 1.21.0 */ + //

TODO: Only meaningful for InetSocketAddress producers. Make this a custom arg? public int getDefaultPort() { return defaultPort; } @@ -371,6 +373,30 @@ public ServiceConfigParser getServiceConfigParser() { return serviceConfigParser; } + /** + * Returns the value of a custom arg named 'key', or {@code null} if it's not set. + * + *

While ordinary {@link Args} should be universally useful and meaningful, custom arguments + * can apply just to resolvers of a certain URI scheme, just to resolvers producing a particular + * type of {@link java.net.SocketAddress}, or even an individual {@link NameResolver} subclass. + * Custom args are identified by an instance of {@link Args.Key} which should be a constant + * defined in a java package and class appropriate for the argument's scope. + * + *

{@link Args} are normally reserved for information in *support* of name resolution, not + * the name to be resolved itself. However, there are rare cases where all or part of the target + * name can't be represented by any standard URI scheme or can't be encoded as a String at all. + * Custom args, in contrast, can hold arbitrary Java types, making them a useful work around in + * these cases. + * + *

Custom args can also be used simply to avoid adding inappropriate deps to the low level + * io.grpc package. + */ + @SuppressWarnings("unchecked") // Cast is safe because all put()s go through the setArg() API. + @Nullable + public T getArg(Key key) { + return customArgs != null ? (T) customArgs.get(key) : null; + } + /** * Returns the {@link ChannelLogger} for the Channel served by this NameResolver. * @@ -424,6 +450,7 @@ public String toString() { .add("proxyDetector", proxyDetector) .add("syncContext", syncContext) .add("serviceConfigParser", serviceConfigParser) + .add("customArgs", customArgs) .add("scheduledExecutorService", scheduledExecutorService) .add("channelLogger", channelLogger) .add("executor", executor) @@ -448,6 +475,7 @@ public Builder toBuilder() { builder.setOffloadExecutor(executor); builder.setOverrideAuthority(overrideAuthority); builder.setMetricRecorder(metricRecorder); + builder.customArgs = cloneCustomArgs(customArgs); return builder; } @@ -475,6 +503,7 @@ public static final class Builder { private Executor executor; private String overrideAuthority; private MetricRecorder metricRecorder; + private IdentityHashMap, Object> customArgs; Builder() { } @@ -561,6 +590,17 @@ public Builder setOverrideAuthority(String authority) { return this; } + /** See {@link Args#getArg(Key)}. */ + public Builder setArg(Key key, T value) { + checkNotNull(key, "key"); + checkNotNull(value, "value"); + if (customArgs == null) { + customArgs = new IdentityHashMap<>(); + } + customArgs.put(key, value); + return this; + } + /** * See {@link Args#getMetricRecorder()}. This is an optional field. */ @@ -575,11 +615,40 @@ public Builder setMetricRecorder(MetricRecorder metricRecorder) { * @since 1.21.0 */ public Args build() { - return - new Args( - defaultPort, proxyDetector, syncContext, serviceConfigParser, - scheduledExecutorService, channelLogger, executor, overrideAuthority, - metricRecorder); + return new Args(this); + } + } + + /** + * Identifies an externally-defined custom argument that can be stored in {@link Args}. + * + *

Uses reference equality so keys should be defined as global constants. + * + * @param type of values that can be stored under this key + */ + @Immutable + @SuppressWarnings("UnusedTypeParameter") + public static final class Key { + private final String debugString; + + private Key(String debugString) { + this.debugString = debugString; + } + + @Override + public String toString() { + return debugString; + } + + /** + * Creates a new instance of {@link Key}. + * + * @param debugString a string used to describe the key, used for debugging. + * @param Key type + * @return a new instance of Key + */ + public static Key create(String debugString) { + return new Key<>(debugString); } } } @@ -877,4 +946,10 @@ public String toString() { } } } + + @Nullable + private static IdentityHashMap, Object> cloneCustomArgs( + @Nullable IdentityHashMap, Object> customArgs) { + return customArgs != null ? new IdentityHashMap<>(customArgs) : null; + } } diff --git a/api/src/main/java/io/grpc/NameResolverRegistry.java b/api/src/main/java/io/grpc/NameResolverRegistry.java index 23eec23fd6a..2648f8de1aa 100644 --- a/api/src/main/java/io/grpc/NameResolverRegistry.java +++ b/api/src/main/java/io/grpc/NameResolverRegistry.java @@ -20,6 +20,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableMap; +import com.google.errorprone.annotations.concurrent.GuardedBy; import java.net.URI; import java.util.ArrayList; import java.util.Collections; @@ -31,7 +32,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.ThreadSafe; /** diff --git a/api/src/main/java/io/grpc/ServerRegistry.java b/api/src/main/java/io/grpc/ServerRegistry.java index a083e45a000..5b9c8c558e7 100644 --- a/api/src/main/java/io/grpc/ServerRegistry.java +++ b/api/src/main/java/io/grpc/ServerRegistry.java @@ -18,6 +18,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; +import com.google.errorprone.annotations.concurrent.GuardedBy; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -25,7 +26,6 @@ import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.ThreadSafe; /** diff --git a/api/src/main/java/io/grpc/Status.java b/api/src/main/java/io/grpc/Status.java index 5d7dd30df01..38cd9581f8e 100644 --- a/api/src/main/java/io/grpc/Status.java +++ b/api/src/main/java/io/grpc/Status.java @@ -23,6 +23,7 @@ import com.google.common.base.MoreObjects; import com.google.common.base.Objects; +import com.google.errorprone.annotations.CheckReturnValue; import io.grpc.Metadata.TrustedAsciiMarshaller; import java.nio.ByteBuffer; import java.util.ArrayList; @@ -30,7 +31,6 @@ import java.util.Collections; import java.util.List; import java.util.TreeMap; -import javax.annotation.CheckReturnValue; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; diff --git a/api/src/main/java/io/grpc/StatusException.java b/api/src/main/java/io/grpc/StatusException.java index b719f881132..f9416bf72e3 100644 --- a/api/src/main/java/io/grpc/StatusException.java +++ b/api/src/main/java/io/grpc/StatusException.java @@ -44,12 +44,7 @@ public StatusException(Status status) { * @since 1.0.0 */ public StatusException(Status status, @Nullable Metadata trailers) { - this(status, trailers, /*fillInStackTrace=*/ true); - } - - StatusException(Status status, @Nullable Metadata trailers, boolean fillInStackTrace) { - super(Status.formatThrowableMessage(status), status.getCause(), - /* enableSuppression */ true, /* writableStackTrace */fillInStackTrace); + super(Status.formatThrowableMessage(status), status.getCause()); this.status = status; this.trailers = trailers; } diff --git a/api/src/main/java/io/grpc/StatusRuntimeException.java b/api/src/main/java/io/grpc/StatusRuntimeException.java index 9465e4c38cd..dd22d6b2486 100644 --- a/api/src/main/java/io/grpc/StatusRuntimeException.java +++ b/api/src/main/java/io/grpc/StatusRuntimeException.java @@ -45,12 +45,7 @@ public StatusRuntimeException(Status status) { * @since 1.0.0 */ public StatusRuntimeException(Status status, @Nullable Metadata trailers) { - this(status, trailers, /*fillInStackTrace=*/ true); - } - - StatusRuntimeException(Status status, @Nullable Metadata trailers, boolean fillInStackTrace) { - super(Status.formatThrowableMessage(status), status.getCause(), - /* enable suppressions */ true, /* writableStackTrace */ fillInStackTrace); + super(Status.formatThrowableMessage(status), status.getCause()); this.status = status; this.trailers = trailers; } diff --git a/api/src/main/java/io/grpc/TimeUtils.java b/api/src/main/java/io/grpc/TimeUtils.java index c3031f13d94..01b8c158822 100644 --- a/api/src/main/java/io/grpc/TimeUtils.java +++ b/api/src/main/java/io/grpc/TimeUtils.java @@ -21,6 +21,7 @@ final class TimeUtils { private TimeUtils() {} + @IgnoreJRERequirement static long convertToNanos(Duration duration) { try { return duration.toNanos(); diff --git a/api/src/test/java/io/grpc/CallOptionsTest.java b/api/src/test/java/io/grpc/CallOptionsTest.java index d74c74ccd66..65fb7ff3bf2 100644 --- a/api/src/test/java/io/grpc/CallOptionsTest.java +++ b/api/src/test/java/io/grpc/CallOptionsTest.java @@ -152,6 +152,7 @@ public void withDeadlineAfter() { } @Test + @IgnoreJRERequirement public void withDeadlineAfterDuration() { Deadline actual = CallOptions.DEFAULT.withDeadlineAfter(Duration.ofMinutes(1L)).getDeadline(); Deadline expected = Deadline.after(1, MINUTES); diff --git a/api/src/test/java/io/grpc/NameResolverTest.java b/api/src/test/java/io/grpc/NameResolverTest.java index 1a7c59f8df5..ae8c080bd5c 100644 --- a/api/src/test/java/io/grpc/NameResolverTest.java +++ b/api/src/test/java/io/grpc/NameResolverTest.java @@ -47,9 +47,13 @@ public class NameResolverTest { private static final List ADDRESSES = Collections.singletonList( new EquivalentAddressGroup(new FakeSocketAddress("fake-address-1"), Attributes.EMPTY)); - private static final Attributes.Key YOLO_KEY = Attributes.Key.create("yolo"); - private static Attributes ATTRIBUTES = Attributes.newBuilder() - .set(YOLO_KEY, "To be, or not to be?").build(); + private static final Attributes.Key YOLO_ATTR_KEY = Attributes.Key.create("yolo"); + private static Attributes ATTRIBUTES = + Attributes.newBuilder().set(YOLO_ATTR_KEY, "To be, or not to be?").build(); + private static final NameResolver.Args.Key FOO_ARG_KEY = + NameResolver.Args.Key.create("foo"); + private static final NameResolver.Args.Key BAR_ARG_KEY = + NameResolver.Args.Key.create("bar"); private static ConfigOrError CONFIG = ConfigOrError.fromConfig("foo"); @Rule @@ -65,6 +69,7 @@ public class NameResolverTest { private final Executor executor = Executors.newSingleThreadExecutor(); private final String overrideAuthority = "grpc.io"; private final MetricRecorder metricRecorder = new MetricRecorder() {}; + private final int customArgValue = 42; @Mock NameResolver.Listener mockListener; @Test @@ -79,6 +84,8 @@ public void args() { assertThat(args.getOffloadExecutor()).isSameInstanceAs(executor); assertThat(args.getOverrideAuthority()).isSameInstanceAs(overrideAuthority); assertThat(args.getMetricRecorder()).isSameInstanceAs(metricRecorder); + assertThat(args.getArg(FOO_ARG_KEY)).isEqualTo(customArgValue); + assertThat(args.getArg(BAR_ARG_KEY)).isNull(); NameResolver.Args args2 = args.toBuilder().build(); assertThat(args2.getDefaultPort()).isEqualTo(defaultPort); @@ -90,6 +97,8 @@ public void args() { assertThat(args2.getOffloadExecutor()).isSameInstanceAs(executor); assertThat(args2.getOverrideAuthority()).isSameInstanceAs(overrideAuthority); assertThat(args.getMetricRecorder()).isSameInstanceAs(metricRecorder); + assertThat(args.getArg(FOO_ARG_KEY)).isEqualTo(customArgValue); + assertThat(args.getArg(BAR_ARG_KEY)).isNull(); assertThat(args2).isNotSameInstanceAs(args); assertThat(args2).isNotEqualTo(args); @@ -106,6 +115,7 @@ private NameResolver.Args createArgs() { .setOffloadExecutor(executor) .setOverrideAuthority(overrideAuthority) .setMetricRecorder(metricRecorder) + .setArg(FOO_ARG_KEY, customArgValue) .build(); } diff --git a/api/src/test/java/io/grpc/StatusExceptionTest.java b/api/src/test/java/io/grpc/StatusExceptionTest.java index dd0d12dccda..410cfb2289a 100644 --- a/api/src/test/java/io/grpc/StatusExceptionTest.java +++ b/api/src/test/java/io/grpc/StatusExceptionTest.java @@ -28,14 +28,6 @@ @RunWith(JUnit4.class) public class StatusExceptionTest { - @Test - public void internalCtorRemovesStack() { - StackTraceElement[] trace = - new StatusException(Status.CANCELLED, null, false) {}.getStackTrace(); - - assertThat(trace).isEmpty(); - } - @Test public void normalCtorKeepsStack() { StackTraceElement[] trace = diff --git a/api/src/test/java/io/grpc/StatusRuntimeExceptionTest.java b/api/src/test/java/io/grpc/StatusRuntimeExceptionTest.java index ab20c111254..d965ed86253 100644 --- a/api/src/test/java/io/grpc/StatusRuntimeExceptionTest.java +++ b/api/src/test/java/io/grpc/StatusRuntimeExceptionTest.java @@ -31,7 +31,7 @@ public class StatusRuntimeExceptionTest { @Test public void internalCtorRemovesStack() { StackTraceElement[] trace = - new StatusRuntimeException(Status.CANCELLED, null, false) {}.getStackTrace(); + new InternalStatusRuntimeException(Status.CANCELLED, null) {}.getStackTrace(); assertThat(trace).isEmpty(); } diff --git a/api/src/test/java/io/grpc/SynchronizationContextTest.java b/api/src/test/java/io/grpc/SynchronizationContextTest.java index f0797df227e..668f5ae4d6d 100644 --- a/api/src/test/java/io/grpc/SynchronizationContextTest.java +++ b/api/src/test/java/io/grpc/SynchronizationContextTest.java @@ -248,6 +248,7 @@ public void schedule() { } @Test + @IgnoreJRERequirement public void scheduleDuration() { MockScheduledExecutorService executorService = new MockScheduledExecutorService(); ScheduledHandle handle = @@ -265,6 +266,7 @@ public void scheduleDuration() { } @Test + @IgnoreJRERequirement public void scheduleWithFixedDelayDuration() { MockScheduledExecutorService executorService = new MockScheduledExecutorService(); ScheduledHandle handle = @@ -402,4 +404,4 @@ static class MockScheduledExecutorService extends ForwardingScheduledExecutorSer return future = super.scheduleWithFixedDelay(command, intialDelay, delay, unit); } } -} \ No newline at end of file +} diff --git a/api/src/test/java/io/grpc/TimeUtilsTest.java b/api/src/test/java/io/grpc/TimeUtilsTest.java index 4faaa9cbf6d..728b8512cd7 100644 --- a/api/src/test/java/io/grpc/TimeUtilsTest.java +++ b/api/src/test/java/io/grpc/TimeUtilsTest.java @@ -25,6 +25,7 @@ /** Unit tests for {@link TimeUtils}. */ @RunWith(JUnit4.class) +@IgnoreJRERequirement public class TimeUtilsTest { @Test @@ -56,4 +57,4 @@ public void testConvertTooLargeNegativeDuration() { assertEquals(Long.MIN_VALUE, TimeUtils.convertToNanos(duration)); } -} \ No newline at end of file +} diff --git a/api/src/testFixtures/java/io/grpc/testing/DeadlineSubject.java b/api/src/testFixtures/java/io/grpc/testing/DeadlineSubject.java index 94ab8fb9b18..c2b4d8412a7 100644 --- a/api/src/testFixtures/java/io/grpc/testing/DeadlineSubject.java +++ b/api/src/testFixtures/java/io/grpc/testing/DeadlineSubject.java @@ -24,9 +24,9 @@ import com.google.common.truth.ComparableSubject; import com.google.common.truth.FailureMetadata; import com.google.common.truth.Subject; +import com.google.errorprone.annotations.CheckReturnValue; import io.grpc.Deadline; import java.util.concurrent.TimeUnit; -import javax.annotation.CheckReturnValue; import javax.annotation.Nullable; /** Propositions for {@link Deadline} subjects. */ diff --git a/auth/build.gradle b/auth/build.gradle index 78bb720601b..d56802c14ca 100644 --- a/auth/build.gradle +++ b/auth/build.gradle @@ -22,6 +22,14 @@ dependencies { project(':grpc-core'), project(":grpc-context"), // Override google-auth dependency with our newer version libraries.google.auth.oauth2Http - signature libraries.signature.java - signature libraries.signature.android + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } + signature (libraries.signature.android) { + artifact { + extension = "signature" + } + } } diff --git a/authz/build.gradle b/authz/build.gradle index 60c86ca0dba..b72088bfbaa 100644 --- a/authz/build.gradle +++ b/authz/build.gradle @@ -26,7 +26,11 @@ dependencies { shadow configurations.implementation.getDependencies().minus([xdsDependency]) shadow project(path: ':grpc-xds', configuration: 'shadow') - signature libraries.signature.java + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } } tasks.named("jar").configure { diff --git a/benchmarks/build.gradle b/benchmarks/build.gradle index d00c0d76ebe..bf043106050 100644 --- a/benchmarks/build.gradle +++ b/benchmarks/build.gradle @@ -43,7 +43,11 @@ dependencies { testImplementation libraries.junit, libraries.mockito.core - signature libraries.signature.java + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } } import net.ltgt.gradle.errorprone.CheckSeverity diff --git a/benchmarks/src/generated/main/grpc/io/grpc/benchmarks/proto/BenchmarkServiceGrpc.java b/benchmarks/src/generated/main/grpc/io/grpc/benchmarks/proto/BenchmarkServiceGrpc.java index e62c2274ee9..242d4551d6e 100644 --- a/benchmarks/src/generated/main/grpc/io/grpc/benchmarks/proto/BenchmarkServiceGrpc.java +++ b/benchmarks/src/generated/main/grpc/io/grpc/benchmarks/proto/BenchmarkServiceGrpc.java @@ -184,6 +184,21 @@ public BenchmarkServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions return BenchmarkServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static BenchmarkServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public BenchmarkServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new BenchmarkServiceBlockingV2Stub(channel, callOptions); + } + }; + return BenchmarkServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -367,6 +382,87 @@ public io.grpc.stub.StreamObserver { + private BenchmarkServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected BenchmarkServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new BenchmarkServiceBlockingV2Stub(channel, callOptions); + } + + /** + *

+     * One request followed by one response.
+     * The server returns the client payload as-is.
+     * 
+ */ + public io.grpc.benchmarks.proto.Messages.SimpleResponse unaryCall(io.grpc.benchmarks.proto.Messages.SimpleRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getUnaryCallMethod(), getCallOptions(), request); + } + + /** + *
+     * Repeated sequence of one request followed by one response.
+     * Should be called streaming ping-pong
+     * The server returns the client payload as-is on each response
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + streamingCall() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getStreamingCallMethod(), getCallOptions()); + } + + /** + *
+     * Single-sided unbounded streaming from client to server
+     * The server returns the client payload as-is once the client does WritesDone
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + streamingFromClient() { + return io.grpc.stub.ClientCalls.blockingClientStreamingCall( + getChannel(), getStreamingFromClientMethod(), getCallOptions()); + } + + /** + *
+     * Single-sided unbounded streaming from server to client
+     * The server repeatedly returns the client payload as-is
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + streamingFromServer(io.grpc.benchmarks.proto.Messages.SimpleRequest request) { + return io.grpc.stub.ClientCalls.blockingV2ServerStreamingCall( + getChannel(), getStreamingFromServerMethod(), getCallOptions(), request); + } + + /** + *
+     * Two-sided unbounded streaming between server to client
+     * Both sides send the content of their own choice to the other
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + streamingBothWays() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getStreamingBothWaysMethod(), getCallOptions()); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service BenchmarkService. + */ public static final class BenchmarkServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private BenchmarkServiceBlockingStub( diff --git a/benchmarks/src/generated/main/grpc/io/grpc/benchmarks/proto/ReportQpsScenarioServiceGrpc.java b/benchmarks/src/generated/main/grpc/io/grpc/benchmarks/proto/ReportQpsScenarioServiceGrpc.java index b24c3813c19..8f466185ea0 100644 --- a/benchmarks/src/generated/main/grpc/io/grpc/benchmarks/proto/ReportQpsScenarioServiceGrpc.java +++ b/benchmarks/src/generated/main/grpc/io/grpc/benchmarks/proto/ReportQpsScenarioServiceGrpc.java @@ -60,6 +60,21 @@ public ReportQpsScenarioServiceStub newStub(io.grpc.Channel channel, io.grpc.Cal return ReportQpsScenarioServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static ReportQpsScenarioServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public ReportQpsScenarioServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new ReportQpsScenarioServiceBlockingV2Stub(channel, callOptions); + } + }; + return ReportQpsScenarioServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -147,6 +162,33 @@ public void reportScenario(io.grpc.benchmarks.proto.Control.ScenarioResult reque /** * A stub to allow clients to do synchronous rpc calls to service ReportQpsScenarioService. */ + public static final class ReportQpsScenarioServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private ReportQpsScenarioServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected ReportQpsScenarioServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new ReportQpsScenarioServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * Report results of a QPS test benchmark scenario.
+     * 
+ */ + public io.grpc.benchmarks.proto.Control.Void reportScenario(io.grpc.benchmarks.proto.Control.ScenarioResult request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getReportScenarioMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service ReportQpsScenarioService. + */ public static final class ReportQpsScenarioServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private ReportQpsScenarioServiceBlockingStub( diff --git a/benchmarks/src/generated/main/grpc/io/grpc/benchmarks/proto/WorkerServiceGrpc.java b/benchmarks/src/generated/main/grpc/io/grpc/benchmarks/proto/WorkerServiceGrpc.java index 0ee6797c8e3..11859482972 100644 --- a/benchmarks/src/generated/main/grpc/io/grpc/benchmarks/proto/WorkerServiceGrpc.java +++ b/benchmarks/src/generated/main/grpc/io/grpc/benchmarks/proto/WorkerServiceGrpc.java @@ -153,6 +153,21 @@ public WorkerServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions ca return WorkerServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static WorkerServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public WorkerServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new WorkerServiceBlockingV2Stub(channel, callOptions); + } + }; + return WorkerServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -323,6 +338,77 @@ public void quitWorker(io.grpc.benchmarks.proto.Control.Void request, /** * A stub to allow clients to do synchronous rpc calls to service WorkerService. */ + public static final class WorkerServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private WorkerServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected WorkerServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new WorkerServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * Start server with specified workload.
+     * First request sent specifies the ServerConfig followed by ServerStatus
+     * response. After that, a "Mark" can be sent anytime to request the latest
+     * stats. Closing the stream will initiate shutdown of the test server
+     * and once the shutdown has finished, the OK status is sent to terminate
+     * this RPC.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + runServer() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getRunServerMethod(), getCallOptions()); + } + + /** + *
+     * Start client with specified workload.
+     * First request sent specifies the ClientConfig followed by ClientStatus
+     * response. After that, a "Mark" can be sent anytime to request the latest
+     * stats. Closing the stream will initiate shutdown of the test client
+     * and once the shutdown has finished, the OK status is sent to terminate
+     * this RPC.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + runClient() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getRunClientMethod(), getCallOptions()); + } + + /** + *
+     * Just return the core count - unary call
+     * 
+ */ + public io.grpc.benchmarks.proto.Control.CoreResponse coreCount(io.grpc.benchmarks.proto.Control.CoreRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getCoreCountMethod(), getCallOptions(), request); + } + + /** + *
+     * Quit this worker
+     * 
+ */ + public io.grpc.benchmarks.proto.Control.Void quitWorker(io.grpc.benchmarks.proto.Control.Void request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getQuitWorkerMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service WorkerService. + */ public static final class WorkerServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private WorkerServiceBlockingStub( diff --git a/binder/build.gradle b/binder/build.gradle index e18361e08b3..3390e02fce7 100644 --- a/binder/build.gradle +++ b/binder/build.gradle @@ -32,7 +32,6 @@ android { repositories { google() - mavenCentral() } dependencies { diff --git a/binder/src/androidTest/java/io/grpc/binder/HostServices.java b/binder/src/androidTest/java/io/grpc/binder/HostServices.java index 4aa46e8254a..5d4a06a27fe 100644 --- a/binder/src/androidTest/java/io/grpc/binder/HostServices.java +++ b/binder/src/androidTest/java/io/grpc/binder/HostServices.java @@ -29,6 +29,7 @@ import androidx.lifecycle.LifecycleService; import com.google.auto.value.AutoValue; import com.google.common.base.Supplier; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Server; import java.io.IOException; import java.util.HashMap; @@ -38,7 +39,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; /** * A test helper class for creating android services to host gRPC servers. diff --git a/binder/src/androidTest/java/io/grpc/binder/internal/BinderClientTransportTest.java b/binder/src/androidTest/java/io/grpc/binder/internal/BinderClientTransportTest.java index c84a1fc296f..33c127f97a7 100644 --- a/binder/src/androidTest/java/io/grpc/binder/internal/BinderClientTransportTest.java +++ b/binder/src/androidTest/java/io/grpc/binder/internal/BinderClientTransportTest.java @@ -27,6 +27,7 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; +import com.google.errorprone.annotations.concurrent.GuardedBy; import com.google.protobuf.Empty; import io.grpc.CallOptions; import io.grpc.ClientStreamTracer; @@ -64,7 +65,6 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; import org.junit.After; import org.junit.Before; import org.junit.Test; diff --git a/binder/src/main/java/io/grpc/binder/ApiConstants.java b/binder/src/main/java/io/grpc/binder/ApiConstants.java index 43e94338fdc..292c580c2b8 100644 --- a/binder/src/main/java/io/grpc/binder/ApiConstants.java +++ b/binder/src/main/java/io/grpc/binder/ApiConstants.java @@ -17,7 +17,9 @@ package io.grpc.binder; import android.content.Intent; +import android.os.UserHandle; import io.grpc.ExperimentalApi; +import io.grpc.NameResolver; /** Constant parts of the gRPC binder transport public API. */ @ExperimentalApi("https://github.com/grpc/grpc-java/issues/8022") @@ -29,4 +31,16 @@ private ApiConstants() {} * themselves in a {@link android.app.Service#onBind(Intent)} call. */ public static final String ACTION_BIND = "grpc.io.action.BIND"; + + /** + * Specifies the Android user in which target URIs should be resolved. + * + *

{@link UserHandle} can't reasonably be encoded in a target URI string. Instead, all + * {@link io.grpc.NameResolverProvider}s producing {@link AndroidComponentAddress}es should let + * clients address servers in another Android user using this argument. + * + *

See also {@link AndroidComponentAddress#getTargetUser()}. + */ + public static final NameResolver.Args.Key TARGET_ANDROID_USER = + NameResolver.Args.Key.create("target-android-user"); } diff --git a/binder/src/main/java/io/grpc/binder/AsyncSecurityPolicy.java b/binder/src/main/java/io/grpc/binder/AsyncSecurityPolicy.java index 2a37e6fd517..5b17ad35977 100644 --- a/binder/src/main/java/io/grpc/binder/AsyncSecurityPolicy.java +++ b/binder/src/main/java/io/grpc/binder/AsyncSecurityPolicy.java @@ -17,11 +17,11 @@ package io.grpc.binder; import com.google.common.util.concurrent.ListenableFuture; +import com.google.errorprone.annotations.CheckReturnValue; import io.grpc.ExperimentalApi; import io.grpc.Status; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; -import javax.annotation.CheckReturnValue; /** * Decides whether a given Android UID is authorized to access some resource. diff --git a/binder/src/main/java/io/grpc/binder/SecurityPolicy.java b/binder/src/main/java/io/grpc/binder/SecurityPolicy.java index e539f17e394..261e5223a0f 100644 --- a/binder/src/main/java/io/grpc/binder/SecurityPolicy.java +++ b/binder/src/main/java/io/grpc/binder/SecurityPolicy.java @@ -16,8 +16,8 @@ package io.grpc.binder; +import com.google.errorprone.annotations.CheckReturnValue; import io.grpc.Status; -import javax.annotation.CheckReturnValue; /** * Decides whether a given Android UID is authorized to access some resource. diff --git a/binder/src/main/java/io/grpc/binder/ServerSecurityPolicy.java b/binder/src/main/java/io/grpc/binder/ServerSecurityPolicy.java index 6a9361c0eaf..4786a5e6cc4 100644 --- a/binder/src/main/java/io/grpc/binder/ServerSecurityPolicy.java +++ b/binder/src/main/java/io/grpc/binder/ServerSecurityPolicy.java @@ -19,10 +19,10 @@ import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import com.google.errorprone.annotations.CheckReturnValue; import io.grpc.Status; import java.util.HashMap; import java.util.Map; -import javax.annotation.CheckReturnValue; /** * A security policy for a gRPC server. diff --git a/binder/src/main/java/io/grpc/binder/UntrustedSecurityPolicies.java b/binder/src/main/java/io/grpc/binder/UntrustedSecurityPolicies.java index 64d8ac1426a..44612a82109 100644 --- a/binder/src/main/java/io/grpc/binder/UntrustedSecurityPolicies.java +++ b/binder/src/main/java/io/grpc/binder/UntrustedSecurityPolicies.java @@ -16,9 +16,9 @@ package io.grpc.binder; +import com.google.errorprone.annotations.CheckReturnValue; import io.grpc.ExperimentalApi; import io.grpc.Status; -import javax.annotation.CheckReturnValue; /** Static factory methods for creating untrusted security policies. */ @CheckReturnValue diff --git a/binder/src/main/java/io/grpc/binder/internal/ActiveTransportTracker.java b/binder/src/main/java/io/grpc/binder/internal/ActiveTransportTracker.java index ad410186486..2bfa9fea4cb 100644 --- a/binder/src/main/java/io/grpc/binder/internal/ActiveTransportTracker.java +++ b/binder/src/main/java/io/grpc/binder/internal/ActiveTransportTracker.java @@ -2,13 +2,13 @@ import static com.google.common.base.Preconditions.checkState; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Attributes; import io.grpc.Metadata; import io.grpc.internal.ServerListener; import io.grpc.internal.ServerStream; import io.grpc.internal.ServerTransport; import io.grpc.internal.ServerTransportListener; -import javax.annotation.concurrent.GuardedBy; /** * Tracks which {@link BinderTransport.BinderServerTransport} are currently active and allows diff --git a/binder/src/main/java/io/grpc/binder/internal/BinderServer.java b/binder/src/main/java/io/grpc/binder/internal/BinderServer.java index 0ad54fb74d1..6b8347390b9 100644 --- a/binder/src/main/java/io/grpc/binder/internal/BinderServer.java +++ b/binder/src/main/java/io/grpc/binder/internal/BinderServer.java @@ -25,6 +25,7 @@ import android.os.Parcel; import android.os.RemoteException; import com.google.common.collect.ImmutableList; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Attributes; import io.grpc.Grpc; import io.grpc.InternalChannelz.SocketStats; @@ -48,7 +49,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.ThreadSafe; /** diff --git a/binder/src/main/java/io/grpc/binder/internal/BinderTransport.java b/binder/src/main/java/io/grpc/binder/internal/BinderTransport.java index 254ad5bb407..f61c455edd5 100644 --- a/binder/src/main/java/io/grpc/binder/internal/BinderTransport.java +++ b/binder/src/main/java/io/grpc/binder/internal/BinderTransport.java @@ -35,6 +35,8 @@ import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import com.google.errorprone.annotations.CheckReturnValue; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Attributes; import io.grpc.CallOptions; import io.grpc.ClientStreamTracer; @@ -78,9 +80,7 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.logging.Level; import java.util.logging.Logger; -import javax.annotation.CheckReturnValue; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.ThreadSafe; /** diff --git a/binder/src/main/java/io/grpc/binder/internal/BinderTransportSecurity.java b/binder/src/main/java/io/grpc/binder/internal/BinderTransportSecurity.java index 430eee3e041..6f95ef8a83c 100644 --- a/binder/src/main/java/io/grpc/binder/internal/BinderTransportSecurity.java +++ b/binder/src/main/java/io/grpc/binder/internal/BinderTransportSecurity.java @@ -20,6 +20,7 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; +import com.google.errorprone.annotations.CheckReturnValue; import io.grpc.Attributes; import io.grpc.Internal; import io.grpc.Metadata; @@ -35,7 +36,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; -import javax.annotation.CheckReturnValue; import javax.annotation.Nullable; /** diff --git a/binder/src/main/java/io/grpc/binder/internal/FlowController.java b/binder/src/main/java/io/grpc/binder/internal/FlowController.java index 1972ea00e6c..135f363a01e 100644 --- a/binder/src/main/java/io/grpc/binder/internal/FlowController.java +++ b/binder/src/main/java/io/grpc/binder/internal/FlowController.java @@ -15,7 +15,7 @@ */ package io.grpc.binder.internal; -import javax.annotation.concurrent.GuardedBy; +import com.google.errorprone.annotations.concurrent.GuardedBy; /** Keeps track of the number of bytes on the wire in a single direction. */ final class FlowController { diff --git a/binder/src/main/java/io/grpc/binder/internal/Inbound.java b/binder/src/main/java/io/grpc/binder/internal/Inbound.java index 19c0e4a0f08..50654297c74 100644 --- a/binder/src/main/java/io/grpc/binder/internal/Inbound.java +++ b/binder/src/main/java/io/grpc/binder/internal/Inbound.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkState; import android.os.Parcel; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Attributes; import io.grpc.Metadata; import io.grpc.Status; @@ -34,7 +35,6 @@ import java.io.InputStream; import java.util.ArrayList; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; /** * Handles incoming binder transactions for a single stream, turning those transactions into calls diff --git a/binder/src/main/java/io/grpc/binder/internal/Outbound.java b/binder/src/main/java/io/grpc/binder/internal/Outbound.java index e2896be02a1..f395fe1701f 100644 --- a/binder/src/main/java/io/grpc/binder/internal/Outbound.java +++ b/binder/src/main/java/io/grpc/binder/internal/Outbound.java @@ -22,6 +22,7 @@ import static java.lang.Math.max; import android.os.Parcel; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Deadline; import io.grpc.Metadata; import io.grpc.MethodDescriptor; @@ -34,7 +35,6 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; /** * Sends the set of outbound transactions for a single BinderStream (rpc). diff --git a/binder/src/main/java/io/grpc/binder/internal/PingTracker.java b/binder/src/main/java/io/grpc/binder/internal/PingTracker.java index 33fcb43918f..ab20af4d6ef 100644 --- a/binder/src/main/java/io/grpc/binder/internal/PingTracker.java +++ b/binder/src/main/java/io/grpc/binder/internal/PingTracker.java @@ -17,12 +17,12 @@ package io.grpc.binder.internal; import com.google.common.base.Ticker; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Status; import io.grpc.StatusException; import io.grpc.internal.ClientTransport.PingCallback; import java.util.concurrent.Executor; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; /** * Tracks an ongoing ping request for a client-side binder transport. We only handle a single active diff --git a/binder/src/main/java/io/grpc/binder/internal/ServiceBinding.java b/binder/src/main/java/io/grpc/binder/internal/ServiceBinding.java index 76f1d7aa9f7..ee171140045 100644 --- a/binder/src/main/java/io/grpc/binder/internal/ServiceBinding.java +++ b/binder/src/main/java/io/grpc/binder/internal/ServiceBinding.java @@ -28,13 +28,13 @@ import androidx.annotation.AnyThread; import androidx.annotation.MainThread; import com.google.common.annotations.VisibleForTesting; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Status; import io.grpc.binder.BinderChannelCredentials; import java.util.concurrent.Executor; import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.ThreadSafe; /** diff --git a/build.gradle b/build.gradle index 52ca19ab4ba..09c78735776 100644 --- a/build.gradle +++ b/build.gradle @@ -21,13 +21,28 @@ subprojects { apply plugin: "net.ltgt.errorprone" group = "io.grpc" - version = "1.70.0-SNAPSHOT" // CURRENT_GRPC_VERSION + version = "1.71.0-SNAPSHOT" // CURRENT_GRPC_VERSION repositories { maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" } - mavenCentral() - mavenLocal() + url "https://maven-central.storage-download.googleapis.com/maven2/" + metadataSources { + mavenPom() + ignoreGradleMetadataRedirection() + } + } + mavenCentral() { + metadataSources { + mavenPom() + ignoreGradleMetadataRedirection() + } + } + mavenLocal() { + metadataSources { + mavenPom() + ignoreGradleMetadataRedirection() + } + } } tasks.withType(JavaCompile).configureEach { diff --git a/buildscripts/checkstyle.xml b/buildscripts/checkstyle.xml index 035b1dfc900..0ec8ecc79ce 100644 --- a/buildscripts/checkstyle.xml +++ b/buildscripts/checkstyle.xml @@ -38,6 +38,12 @@ + + + + + + diff --git a/census/BUILD.bazel b/census/BUILD.bazel index aec16c46af0..36be88fc3d8 100644 --- a/census/BUILD.bazel +++ b/census/BUILD.bazel @@ -10,6 +10,7 @@ java_library( "//api", "//context", artifact("com.google.code.findbugs:jsr305"), + artifact("com.google.errorprone:error_prone_annotations"), artifact("com.google.guava:guava"), artifact("io.opencensus:opencensus-api"), artifact("io.opencensus:opencensus-contrib-grpc-metrics"), diff --git a/census/build.gradle b/census/build.gradle index c1dc53e4c05..0993488ff83 100644 --- a/census/build.gradle +++ b/census/build.gradle @@ -27,8 +27,16 @@ dependencies { project(':grpc-testing'), libraries.opencensus.impl - signature libraries.signature.java - signature libraries.signature.android + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } + signature (libraries.signature.android) { + artifact { + extension = "signature" + } + } } tasks.named("javadoc").configure { diff --git a/census/src/main/java/io/grpc/census/CensusStatsModule.java b/census/src/main/java/io/grpc/census/CensusStatsModule.java index ad16bef9604..8f571ceb627 100644 --- a/census/src/main/java/io/grpc/census/CensusStatsModule.java +++ b/census/src/main/java/io/grpc/census/CensusStatsModule.java @@ -22,6 +22,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Stopwatch; import com.google.common.base.Supplier; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Attributes; import io.grpc.CallOptions; import io.grpc.Channel; @@ -62,7 +63,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; /** * Provides factories for {@link StreamTracer} that records stats to Census. diff --git a/compiler/src/java_plugin/cpp/java_generator.cpp b/compiler/src/java_plugin/cpp/java_generator.cpp index 8693fad1b66..df96bb1c1b2 100644 --- a/compiler/src/java_plugin/cpp/java_generator.cpp +++ b/compiler/src/java_plugin/cpp/java_generator.cpp @@ -355,13 +355,15 @@ enum StubType { BLOCKING_CLIENT_IMPL = 5, FUTURE_CLIENT_IMPL = 6, ABSTRACT_CLASS = 7, - NONE = 8, + BLOCKING_V2_CLIENT_IMPL = 8, + NONE = 999, }; enum CallType { ASYNC_CALL = 0, BLOCKING_CALL = 1, - FUTURE_CALL = 2 + FUTURE_CALL = 2, + BLOCKING_V2_CALL = 3, }; // TODO(nmittler): Remove once protobuf includes javadoc methods in distribution. @@ -410,6 +412,9 @@ static void GrpcWriteServiceDocComment(Printer* printer, printer->Print(vars, " * A stub to allow clients to do asynchronous rpc calls to service $service$.\n"); break; case BLOCKING_CLIENT_IMPL: + printer->Print(vars, " * A stub to allow clients to do limited synchronous rpc calls to service $service$.\n"); + break; + case BLOCKING_V2_CLIENT_IMPL: printer->Print(vars, " * A stub to allow clients to do synchronous rpc calls to service $service$.\n"); break; case FUTURE_CLIENT_IMPL: @@ -555,6 +560,9 @@ static void PrintStubFactory( case BLOCKING_CLIENT_IMPL: stub_type_name = "Blocking"; break; + case BLOCKING_V2_CLIENT_IMPL: + stub_type_name = "BlockingV2"; + break; default: GRPC_CODEGEN_FAIL << "Cannot generate StubFactory for StubType: " << type; } @@ -597,6 +605,11 @@ static void PrintStub( stub_name += "BlockingStub"; stub_base_class_name = "AbstractBlockingStub"; break; + case BLOCKING_V2_CLIENT_IMPL: + call_type = BLOCKING_V2_CALL; + stub_name += "BlockingV2Stub"; + stub_base_class_name = "AbstractBlockingStub"; + break; case FUTURE_CLIENT_IMPL: call_type = FUTURE_CALL; stub_name += "FutureStub"; @@ -679,13 +692,17 @@ static void PrintStub( // Method signature p->Print("\n"); - // TODO(nmittler): Replace with WriteMethodDocComment once included by the protobuf distro. GrpcWriteMethodDocComment(p, method); if (method->options().deprecated()) { p->Print(*vars, "@$Deprecated$\n"); } + if ((call_type == BLOCKING_CALL && client_streaming && server_streaming) + || (call_type == BLOCKING_V2_CALL && (client_streaming || server_streaming))) { + p->Print(*vars, "@io.grpc.ExperimentalApi(\"https://github.com/grpc/grpc-java/issues/10918\")\n"); + } + if (!interface) { p->Print("public "); } else { @@ -695,7 +712,12 @@ static void PrintStub( case BLOCKING_CALL: GRPC_CODEGEN_CHECK(!client_streaming) << "Blocking client interface with client streaming is unavailable"; - if (server_streaming) { + if (client_streaming && server_streaming) { + p->Print( + *vars, + "$BlockingClientCall$<$input_type$, $output_type$>\n" + " $lower_method_name$()"); + } else if (server_streaming) { // Server streaming p->Print( *vars, @@ -708,6 +730,25 @@ static void PrintStub( "$output_type$ $lower_method_name$($input_type$ request)"); } break; + case BLOCKING_V2_CALL: + if (client_streaming) { // Both Bidi and Client Streaming + p->Print( + *vars, + "$BlockingClientCall$<$input_type$, $output_type$>\n" + " $lower_method_name$()"); + } else if (server_streaming) { + // Server streaming + p->Print( + *vars, + "$BlockingClientCall$\n" + " $lower_method_name$($input_type$ request)"); + } else { + // Simple RPC + p->Print( + *vars, + "$output_type$ $lower_method_name$($input_type$ request)"); + } + break; case ASYNC_CALL: if (client_streaming) { // Bidirectional streaming or client streaming @@ -753,21 +794,46 @@ static void PrintStub( "$method_method_name$(), responseObserver);\n"); } } else if (!interface) { - switch (call_type) { + switch (call_type) { case BLOCKING_CALL: GRPC_CODEGEN_CHECK(!client_streaming) - << "Blocking client streaming interface is not available"; - if (server_streaming) { - (*vars)["calls_method"] = "io.grpc.stub.ClientCalls.blockingServerStreamingCall"; - (*vars)["params"] = "request"; - } else { - (*vars)["calls_method"] = "io.grpc.stub.ClientCalls.blockingUnaryCall"; - (*vars)["params"] = "request"; + << "Blocking client and bidi streaming interface are not available"; + if (server_streaming) { + (*vars)["calls_method"] = "io.grpc.stub.ClientCalls.blockingServerStreamingCall"; + (*vars)["params"] = "request"; + } else { + (*vars)["calls_method"] = "io.grpc.stub.ClientCalls.blockingUnaryCall"; + (*vars)["params"] = "request"; + } + p->Print( + *vars, + "return $calls_method$(\n" + " getChannel(), $method_method_name$(), getCallOptions(), $params$);\n"); + break; + case BLOCKING_V2_CALL: + if (client_streaming) { // client and bidi streaming + if (server_streaming) { + (*vars)["calls_method"] = "io.grpc.stub.ClientCalls.blockingBidiStreamingCall"; + } else { + (*vars)["calls_method"] = "io.grpc.stub.ClientCalls.blockingClientStreamingCall"; + } + p->Print( + *vars, + "return $calls_method$(\n" + " getChannel(), $method_method_name$(), getCallOptions());\n"); + } else { // server streaming and unary + (*vars)["params"] = "request"; + if (server_streaming) { + (*vars)["calls_method"] = "io.grpc.stub.ClientCalls.blockingV2ServerStreamingCall"; + } else { + (*vars)["calls_method"] = "io.grpc.stub.ClientCalls.blockingUnaryCall"; + } + + p->Print( + *vars, + "return $calls_method$(\n" + " getChannel(), $method_method_name$(), getCallOptions(), $params$);\n"); } - p->Print( - *vars, - "return $calls_method$(\n" - " getChannel(), $method_method_name$(), getCallOptions(), $params$);\n"); break; case ASYNC_CALL: if (server_streaming) { @@ -804,7 +870,7 @@ static void PrintStub( "return $calls_method$(\n" " getChannel().newCall($method_method_name$(), getCallOptions()), request);\n"); break; - } + } } else { GRPC_CODEGEN_FAIL << "Do not create Stub interfaces"; } @@ -1173,6 +1239,21 @@ static void PrintService(const ServiceDescriptor* service, p->Outdent(); p->Print("}\n\n"); + // TODO(nmittler): Replace with WriteDocComment once included by protobuf distro. + GrpcWriteDocComment(p, " Creates a new blocking-style stub that supports all types of calls " + "on the service"); + p->Print( + *vars, + "public static $service_name$BlockingV2Stub newBlockingV2Stub(\n" + " $Channel$ channel) {\n"); + p->Indent(); + PrintStubFactory(service, vars, p, BLOCKING_V2_CLIENT_IMPL); + p->Print( + *vars, + "return $service_name$BlockingV2Stub.newStub(factory, channel);\n"); + p->Outdent(); + p->Print("}\n\n"); + // TODO(nmittler): Replace with WriteDocComment once included by protobuf distro. GrpcWriteDocComment(p, " Creates a new blocking-style stub that supports unary and streaming " "output calls on the service"); @@ -1206,6 +1287,7 @@ static void PrintService(const ServiceDescriptor* service, PrintStub(service, vars, p, ASYNC_INTERFACE); PrintAbstractClassStub(service, vars, p); PrintStub(service, vars, p, ASYNC_CLIENT_IMPL); + PrintStub(service, vars, p, BLOCKING_V2_CLIENT_IMPL); PrintStub(service, vars, p, BLOCKING_CLIENT_IMPL); PrintStub(service, vars, p, FUTURE_CLIENT_IMPL); @@ -1257,6 +1339,7 @@ void GenerateService(const ServiceDescriptor* service, vars["RpcMethod"] = "io.grpc.stub.annotations.RpcMethod"; vars["MethodDescriptor"] = "io.grpc.MethodDescriptor"; vars["StreamObserver"] = "io.grpc.stub.StreamObserver"; + vars["BlockingClientCall"] = "io.grpc.stub.BlockingClientCall"; vars["Iterator"] = "java.util.Iterator"; vars["GrpcGenerated"] = "io.grpc.stub.annotations.GrpcGenerated"; vars["ListenableFuture"] = diff --git a/compiler/src/test/golden/TestDeprecatedService.java.txt b/compiler/src/test/golden/TestDeprecatedService.java.txt index 36ff11a160a..e696def7b99 100644 --- a/compiler/src/test/golden/TestDeprecatedService.java.txt +++ b/compiler/src/test/golden/TestDeprecatedService.java.txt @@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName; * */ @javax.annotation.Generated( - value = "by gRPC proto compiler (version 1.70.0-SNAPSHOT)", + value = "by gRPC proto compiler (version 1.71.0-SNAPSHOT)", comments = "Source: grpc/testing/compiler/test.proto") @io.grpc.stub.annotations.GrpcGenerated @java.lang.Deprecated @@ -64,6 +64,21 @@ public final class TestDeprecatedServiceGrpc { return TestDeprecatedServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static TestDeprecatedServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public TestDeprecatedServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new TestDeprecatedServiceBlockingV2Stub(channel, callOptions); + } + }; + return TestDeprecatedServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -169,6 +184,38 @@ public final class TestDeprecatedServiceGrpc { * */ @java.lang.Deprecated + public static final class TestDeprecatedServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private TestDeprecatedServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected TestDeprecatedServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new TestDeprecatedServiceBlockingV2Stub(channel, callOptions); + } + + /** + *

+     * An RPC method that has been deprecated and should generate with Java's @Deprecated annotation
+     * 
+ */ + @java.lang.Deprecated + public io.grpc.testing.compiler.Test.SimpleResponse deprecatedMethod(io.grpc.testing.compiler.Test.SimpleRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getDeprecatedMethodMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service TestDeprecatedService. + *
+   * Test service that has been deprecated and should generate with Java's @Deprecated annotation
+   * 
+ */ + @java.lang.Deprecated public static final class TestDeprecatedServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private TestDeprecatedServiceBlockingStub( diff --git a/compiler/src/test/golden/TestService.java.txt b/compiler/src/test/golden/TestService.java.txt index 69a1b0947b5..c052093cbbc 100644 --- a/compiler/src/test/golden/TestService.java.txt +++ b/compiler/src/test/golden/TestService.java.txt @@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName; * */ @javax.annotation.Generated( - value = "by gRPC proto compiler (version 1.70.0-SNAPSHOT)", + value = "by gRPC proto compiler (version 1.71.0-SNAPSHOT)", comments = "Source: grpc/testing/compiler/test.proto") @io.grpc.stub.annotations.GrpcGenerated public final class TestServiceGrpc { @@ -282,6 +282,21 @@ public final class TestServiceGrpc { return TestServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static TestServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public TestServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new TestServiceBlockingV2Stub(channel, callOptions); + } + }; + return TestServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -546,6 +561,125 @@ public final class TestServiceGrpc { * Test service that supports all call types. * */ + public static final class TestServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private TestServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected TestServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new TestServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * One request followed by one response.
+     * The server returns the client payload as-is.
+     * 
+ */ + public io.grpc.testing.compiler.Test.SimpleResponse unaryCall(io.grpc.testing.compiler.Test.SimpleRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getUnaryCallMethod(), getCallOptions(), request); + } + + /** + *
+     * One request followed by a sequence of responses (streamed download).
+     * The server returns the payload with client desired type and sizes.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + streamingOutputCall(io.grpc.testing.compiler.Test.StreamingOutputCallRequest request) { + return io.grpc.stub.ClientCalls.blockingV2ServerStreamingCall( + getChannel(), getStreamingOutputCallMethod(), getCallOptions(), request); + } + + /** + *
+     * A sequence of requests followed by one response (streamed upload).
+     * The server returns the aggregated size of client payload as the result.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + streamingInputCall() { + return io.grpc.stub.ClientCalls.blockingClientStreamingCall( + getChannel(), getStreamingInputCallMethod(), getCallOptions()); + } + + /** + *
+     * A sequence of requests with each request served by the server immediately.
+     * As one request could lead to multiple responses, this interface
+     * demonstrates the idea of full bidirectionality.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + fullBidiCall() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getFullBidiCallMethod(), getCallOptions()); + } + + /** + *
+     * A sequence of requests followed by a sequence of responses.
+     * The server buffers all the client requests and then serves them in order. A
+     * stream of responses are returned to the client when the server starts with
+     * first request.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + halfBidiCall() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getHalfBidiCallMethod(), getCallOptions()); + } + + /** + *
+     * An RPC method whose Java name collides with a keyword, and whose generated
+     * method should have a '_' appended.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + import_() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getImportMethod(), getCallOptions()); + } + + /** + *
+     * A unary call that is Safe.
+     * 
+ */ + public io.grpc.testing.compiler.Test.SimpleResponse safeCall(io.grpc.testing.compiler.Test.SimpleRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getSafeCallMethod(), getCallOptions(), request); + } + + /** + *
+     * A unary call that is Idempotent.
+     * 
+ */ + public io.grpc.testing.compiler.Test.SimpleResponse idempotentCall(io.grpc.testing.compiler.Test.SimpleRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getIdempotentCallMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service TestService. + *
+   * Test service that supports all call types.
+   * 
+ */ public static final class TestServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private TestServiceBlockingStub( diff --git a/compiler/src/testLite/golden/TestDeprecatedService.java.txt b/compiler/src/testLite/golden/TestDeprecatedService.java.txt index 3a7dba9bbb5..22a57c71523 100644 --- a/compiler/src/testLite/golden/TestDeprecatedService.java.txt +++ b/compiler/src/testLite/golden/TestDeprecatedService.java.txt @@ -60,6 +60,21 @@ public final class TestDeprecatedServiceGrpc { return TestDeprecatedServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static TestDeprecatedServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public TestDeprecatedServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new TestDeprecatedServiceBlockingV2Stub(channel, callOptions); + } + }; + return TestDeprecatedServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -165,6 +180,38 @@ public final class TestDeprecatedServiceGrpc { * */ @java.lang.Deprecated + public static final class TestDeprecatedServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private TestDeprecatedServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected TestDeprecatedServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new TestDeprecatedServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * An RPC method that has been deprecated and should generate with Java's @Deprecated annotation
+     * 
+ */ + @java.lang.Deprecated + public io.grpc.testing.compiler.Test.SimpleResponse deprecatedMethod(io.grpc.testing.compiler.Test.SimpleRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getDeprecatedMethodMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service TestDeprecatedService. + *
+   * Test service that has been deprecated and should generate with Java's @Deprecated annotation
+   * 
+ */ + @java.lang.Deprecated public static final class TestDeprecatedServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private TestDeprecatedServiceBlockingStub( diff --git a/compiler/src/testLite/golden/TestService.java.txt b/compiler/src/testLite/golden/TestService.java.txt index f86fb50d7dc..d13d9959a4a 100644 --- a/compiler/src/testLite/golden/TestService.java.txt +++ b/compiler/src/testLite/golden/TestService.java.txt @@ -271,6 +271,21 @@ public final class TestServiceGrpc { return TestServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static TestServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public TestServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new TestServiceBlockingV2Stub(channel, callOptions); + } + }; + return TestServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -535,6 +550,125 @@ public final class TestServiceGrpc { * Test service that supports all call types. * */ + public static final class TestServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private TestServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected TestServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new TestServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * One request followed by one response.
+     * The server returns the client payload as-is.
+     * 
+ */ + public io.grpc.testing.compiler.Test.SimpleResponse unaryCall(io.grpc.testing.compiler.Test.SimpleRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getUnaryCallMethod(), getCallOptions(), request); + } + + /** + *
+     * One request followed by a sequence of responses (streamed download).
+     * The server returns the payload with client desired type and sizes.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + streamingOutputCall(io.grpc.testing.compiler.Test.StreamingOutputCallRequest request) { + return io.grpc.stub.ClientCalls.blockingV2ServerStreamingCall( + getChannel(), getStreamingOutputCallMethod(), getCallOptions(), request); + } + + /** + *
+     * A sequence of requests followed by one response (streamed upload).
+     * The server returns the aggregated size of client payload as the result.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + streamingInputCall() { + return io.grpc.stub.ClientCalls.blockingClientStreamingCall( + getChannel(), getStreamingInputCallMethod(), getCallOptions()); + } + + /** + *
+     * A sequence of requests with each request served by the server immediately.
+     * As one request could lead to multiple responses, this interface
+     * demonstrates the idea of full bidirectionality.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + fullBidiCall() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getFullBidiCallMethod(), getCallOptions()); + } + + /** + *
+     * A sequence of requests followed by a sequence of responses.
+     * The server buffers all the client requests and then serves them in order. A
+     * stream of responses are returned to the client when the server starts with
+     * first request.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + halfBidiCall() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getHalfBidiCallMethod(), getCallOptions()); + } + + /** + *
+     * An RPC method whose Java name collides with a keyword, and whose generated
+     * method should have a '_' appended.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + import_() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getImportMethod(), getCallOptions()); + } + + /** + *
+     * A unary call that is Safe.
+     * 
+ */ + public io.grpc.testing.compiler.Test.SimpleResponse safeCall(io.grpc.testing.compiler.Test.SimpleRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getSafeCallMethod(), getCallOptions(), request); + } + + /** + *
+     * A unary call that is Idempotent.
+     * 
+ */ + public io.grpc.testing.compiler.Test.SimpleResponse idempotentCall(io.grpc.testing.compiler.Test.SimpleRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getIdempotentCallMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service TestService. + *
+   * Test service that supports all call types.
+   * 
+ */ public static final class TestServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private TestServiceBlockingStub( diff --git a/contextstorage/build.gradle b/contextstorage/build.gradle index 39ea003d462..b1e78ea0e17 100644 --- a/contextstorage/build.gradle +++ b/contextstorage/build.gradle @@ -16,8 +16,16 @@ dependencies { libraries.assertj.core testImplementation 'junit:junit:4.13.1'// opentelemetry.sdk.testing uses compileOnly for assertj - signature libraries.signature.java - signature libraries.signature.android + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } + signature (libraries.signature.android) { + artifact { + extension = "signature" + } + } } tasks.named("jar").configure { diff --git a/core/BUILD.bazel b/core/BUILD.bazel index 35c20628d0b..6dd5199b5c0 100644 --- a/core/BUILD.bazel +++ b/core/BUILD.bazel @@ -17,7 +17,6 @@ java_library( srcs = glob([ "src/main/java/io/grpc/internal/*.java", ]), - javacopts = ["-Xep:DoNotCall:OFF"], # Remove once requiring Bazel 3.4.0+; allows non-final resources = glob([ "src/bazel-internal/resources/**", ]), diff --git a/core/build.gradle b/core/build.gradle index f8a95c37286..2fac9ddba04 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -39,8 +39,16 @@ dependencies { jmh project(':grpc-testing') - signature libraries.signature.java - signature libraries.signature.android + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } + signature (libraries.signature.android) { + artifact { + extension = "signature" + } + } } tasks.named("javadoc").configure { diff --git a/core/src/main/java/io/grpc/internal/AbstractStream.java b/core/src/main/java/io/grpc/internal/AbstractStream.java index 9efc488657b..46cdab7ef28 100644 --- a/core/src/main/java/io/grpc/internal/AbstractStream.java +++ b/core/src/main/java/io/grpc/internal/AbstractStream.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkState; import com.google.common.annotations.VisibleForTesting; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Codec; import io.grpc.Compressor; import io.grpc.Decompressor; @@ -27,13 +28,16 @@ import io.perfmark.PerfMark; import io.perfmark.TaskCloseable; import java.io.InputStream; -import javax.annotation.concurrent.GuardedBy; +import java.util.logging.Level; +import java.util.logging.Logger; /** * The stream and stream state as used by the application. Must only be called from the sending * application thread. */ public abstract class AbstractStream implements Stream { + private static final Logger log = Logger.getLogger(AbstractStream.class.getName()); + /** The framer to use for sending messages. */ protected abstract Framer framer(); @@ -371,6 +375,12 @@ private void notifyIfReady() { boolean doNotify; synchronized (onReadyLock) { doNotify = isReady(); + if (!doNotify && log.isLoggable(Level.FINEST)) { + log.log(Level.FINEST, + "Stream not ready so skip notifying listener.\n" + + "details: allocated/deallocated:{0}/{3}, sent queued: {1}, ready thresh: {2}", + new Object[] {allocated, numSentBytesQueued, onReadyThreshold, deallocated}); + } } if (doNotify) { listener().onReady(); diff --git a/core/src/main/java/io/grpc/internal/CallCredentialsApplyingTransportFactory.java b/core/src/main/java/io/grpc/internal/CallCredentialsApplyingTransportFactory.java index 42631851974..97a74bda97e 100644 --- a/core/src/main/java/io/grpc/internal/CallCredentialsApplyingTransportFactory.java +++ b/core/src/main/java/io/grpc/internal/CallCredentialsApplyingTransportFactory.java @@ -19,6 +19,7 @@ import static com.google.common.base.MoreObjects.firstNonNull; import static com.google.common.base.Preconditions.checkNotNull; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Attributes; import io.grpc.CallCredentials; import io.grpc.CallCredentials.RequestInfo; @@ -38,7 +39,6 @@ import java.util.concurrent.Executor; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicInteger; -import javax.annotation.concurrent.GuardedBy; final class CallCredentialsApplyingTransportFactory implements ClientTransportFactory { private final ClientTransportFactory delegate; diff --git a/core/src/main/java/io/grpc/internal/ChannelTracer.java b/core/src/main/java/io/grpc/internal/ChannelTracer.java index 8c8243c9021..a9730a365cc 100644 --- a/core/src/main/java/io/grpc/internal/ChannelTracer.java +++ b/core/src/main/java/io/grpc/internal/ChannelTracer.java @@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkNotNull; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.ChannelLogger; import io.grpc.InternalChannelz.ChannelStats; import io.grpc.InternalChannelz.ChannelTrace; @@ -31,7 +32,6 @@ import java.util.logging.LogRecord; import java.util.logging.Logger; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; /** * Tracks a collections of channel tracing events for a channel/subchannel. diff --git a/core/src/main/java/io/grpc/internal/ClientTransportFactory.java b/core/src/main/java/io/grpc/internal/ClientTransportFactory.java index d987f9d5068..6c10ced4652 100644 --- a/core/src/main/java/io/grpc/internal/ClientTransportFactory.java +++ b/core/src/main/java/io/grpc/internal/ClientTransportFactory.java @@ -18,6 +18,7 @@ import com.google.common.base.Objects; import com.google.common.base.Preconditions; +import com.google.errorprone.annotations.CheckReturnValue; import io.grpc.Attributes; import io.grpc.CallCredentials; import io.grpc.ChannelCredentials; @@ -27,7 +28,6 @@ import java.net.SocketAddress; import java.util.Collection; import java.util.concurrent.ScheduledExecutorService; -import javax.annotation.CheckReturnValue; import javax.annotation.Nullable; /** Pre-configured factory for creating {@link ConnectionClientTransport} instances. */ diff --git a/core/src/main/java/io/grpc/internal/DelayedClientCall.java b/core/src/main/java/io/grpc/internal/DelayedClientCall.java index 92034e83f45..f2b0c9a3f06 100644 --- a/core/src/main/java/io/grpc/internal/DelayedClientCall.java +++ b/core/src/main/java/io/grpc/internal/DelayedClientCall.java @@ -22,6 +22,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Attributes; import io.grpc.ClientCall; import io.grpc.Context; @@ -38,7 +39,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; /** * A call that queues requests before a real call is ready to be delegated to. diff --git a/core/src/main/java/io/grpc/internal/DelayedClientTransport.java b/core/src/main/java/io/grpc/internal/DelayedClientTransport.java index ae173f4ac26..2ff94b7804a 100644 --- a/core/src/main/java/io/grpc/internal/DelayedClientTransport.java +++ b/core/src/main/java/io/grpc/internal/DelayedClientTransport.java @@ -19,6 +19,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.CallOptions; import io.grpc.ClientStreamTracer; import io.grpc.Context; @@ -39,7 +40,6 @@ import java.util.concurrent.Executor; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; /** * A client transport that queues requests before a real transport is available. When {@link diff --git a/core/src/main/java/io/grpc/internal/DelayedStream.java b/core/src/main/java/io/grpc/internal/DelayedStream.java index c94986a3458..2ca4630d6a1 100644 --- a/core/src/main/java/io/grpc/internal/DelayedStream.java +++ b/core/src/main/java/io/grpc/internal/DelayedStream.java @@ -20,6 +20,8 @@ import static com.google.common.base.Preconditions.checkState; import com.google.common.annotations.VisibleForTesting; +import com.google.errorprone.annotations.CheckReturnValue; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Attributes; import io.grpc.Compressor; import io.grpc.Deadline; @@ -30,8 +32,6 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.List; -import javax.annotation.CheckReturnValue; -import javax.annotation.concurrent.GuardedBy; /** * A stream that queues requests before the transport is available, and delegates to a real stream diff --git a/core/src/main/java/io/grpc/internal/GrpcUtil.java b/core/src/main/java/io/grpc/internal/GrpcUtil.java index 8a65c7d6c2b..fc420195667 100644 --- a/core/src/main/java/io/grpc/internal/GrpcUtil.java +++ b/core/src/main/java/io/grpc/internal/GrpcUtil.java @@ -219,7 +219,7 @@ public byte[] parseAsciiString(byte[] serialized) { public static final Splitter ACCEPT_ENCODING_SPLITTER = Splitter.on(',').trimResults(); - public static final String IMPLEMENTATION_VERSION = "1.70.0-SNAPSHOT"; // CURRENT_GRPC_VERSION + public static final String IMPLEMENTATION_VERSION = "1.71.0-SNAPSHOT"; // CURRENT_GRPC_VERSION /** * The default timeout in nanos for a keepalive ping request. diff --git a/core/src/main/java/io/grpc/internal/Http2Ping.java b/core/src/main/java/io/grpc/internal/Http2Ping.java index 6104d876373..d96ac3ef214 100644 --- a/core/src/main/java/io/grpc/internal/Http2Ping.java +++ b/core/src/main/java/io/grpc/internal/Http2Ping.java @@ -17,6 +17,7 @@ package io.grpc.internal; import com.google.common.base.Stopwatch; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.internal.ClientTransport.PingCallback; import java.util.LinkedHashMap; import java.util.Map; @@ -24,7 +25,6 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; -import javax.annotation.concurrent.GuardedBy; /** * Represents an outstanding PING operation on an HTTP/2 channel. This can be used by HTTP/2-based diff --git a/core/src/main/java/io/grpc/internal/KeepAliveEnforcer.java b/core/src/main/java/io/grpc/internal/KeepAliveEnforcer.java index dd539e75a18..6480336470c 100644 --- a/core/src/main/java/io/grpc/internal/KeepAliveEnforcer.java +++ b/core/src/main/java/io/grpc/internal/KeepAliveEnforcer.java @@ -18,8 +18,8 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; +import com.google.errorprone.annotations.CheckReturnValue; import java.util.concurrent.TimeUnit; -import javax.annotation.CheckReturnValue; /** Monitors the client's PING usage to make sure the rate is permitted. */ public final class KeepAliveEnforcer { diff --git a/core/src/main/java/io/grpc/internal/KeepAliveManager.java b/core/src/main/java/io/grpc/internal/KeepAliveManager.java index 28e2a87276b..aed590c3051 100644 --- a/core/src/main/java/io/grpc/internal/KeepAliveManager.java +++ b/core/src/main/java/io/grpc/internal/KeepAliveManager.java @@ -22,11 +22,11 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Stopwatch; import com.google.common.util.concurrent.MoreExecutors; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Status; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import javax.annotation.concurrent.GuardedBy; /** * Manages keepalive pings. diff --git a/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java b/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java index 88fbf5e2c62..45819954473 100644 --- a/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java +++ b/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java @@ -32,6 +32,7 @@ import com.google.common.base.Supplier; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Attributes; import io.grpc.CallCredentials; import io.grpc.CallOptions; @@ -117,7 +118,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.ThreadSafe; /** A communication channel for making outgoing RPCs. */ @@ -591,8 +591,7 @@ ClientStream newSubstream( this.authorityOverride = builder.authorityOverride; this.metricRecorder = new MetricRecorderImpl(builder.metricSinks, MetricInstrumentRegistry.getDefaultRegistry()); - this.nameResolverArgs = - NameResolver.Args.newBuilder() + NameResolver.Args.Builder nameResolverArgsBuilder = NameResolver.Args.newBuilder() .setDefaultPort(builder.getDefaultPort()) .setProxyDetector(proxyDetector) .setSynchronizationContext(syncContext) @@ -601,8 +600,9 @@ ClientStream newSubstream( .setChannelLogger(channelLogger) .setOffloadExecutor(this.offloadExecutorHolder) .setOverrideAuthority(this.authorityOverride) - .setMetricRecorder(this.metricRecorder) - .build(); + .setMetricRecorder(this.metricRecorder); + builder.copyAllNameResolverCustomArgsTo(nameResolverArgsBuilder); + this.nameResolverArgs = nameResolverArgsBuilder.build(); this.nameResolver = getNameResolver( targetUri, authorityOverride, nameResolverProvider, nameResolverArgs); this.balancerRpcExecutorPool = checkNotNull(balancerRpcExecutorPool, "balancerRpcExecutorPool"); diff --git a/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java b/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java index 48a255472e1..20f7e901ddd 100644 --- a/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java +++ b/core/src/main/java/io/grpc/internal/ManagedChannelImplBuilder.java @@ -55,6 +55,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.IdentityHashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -159,6 +160,8 @@ public static ManagedChannelBuilder forTarget(String target) { final ChannelCredentials channelCredentials; @Nullable final CallCredentials callCredentials; + @Nullable + IdentityHashMap, Object> nameResolverCustomArgs; @Nullable private final SocketAddress directServerAddress; @@ -613,6 +616,24 @@ private static List checkListEntryTypes(List list) { return Collections.unmodifiableList(parsedList); } + @Override + public ManagedChannelImplBuilder setNameResolverArg(NameResolver.Args.Key key, X value) { + if (nameResolverCustomArgs == null) { + nameResolverCustomArgs = new IdentityHashMap<>(); + } + nameResolverCustomArgs.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + @SuppressWarnings("unchecked") // This cast is safe because of setNameResolverArg()'s signature. + void copyAllNameResolverCustomArgsTo(NameResolver.Args.Builder dest) { + if (nameResolverCustomArgs != null) { + for (Map.Entry, Object> entry : nameResolverCustomArgs.entrySet()) { + dest.setArg((NameResolver.Args.Key) entry.getKey(), entry.getValue()); + } + } + } + @Override public ManagedChannelImplBuilder disableServiceConfigLookUp() { this.lookUpServiceConfig = false; diff --git a/core/src/main/java/io/grpc/internal/ManagedClientTransport.java b/core/src/main/java/io/grpc/internal/ManagedClientTransport.java index 5f8fe52ef6b..184a4d98955 100644 --- a/core/src/main/java/io/grpc/internal/ManagedClientTransport.java +++ b/core/src/main/java/io/grpc/internal/ManagedClientTransport.java @@ -16,9 +16,9 @@ package io.grpc.internal; +import com.google.errorprone.annotations.CheckReturnValue; import io.grpc.Attributes; import io.grpc.Status; -import javax.annotation.CheckReturnValue; import javax.annotation.Nullable; import javax.annotation.concurrent.ThreadSafe; diff --git a/core/src/main/java/io/grpc/internal/MetadataApplierImpl.java b/core/src/main/java/io/grpc/internal/MetadataApplierImpl.java index 12cab15053f..09a1018c11c 100644 --- a/core/src/main/java/io/grpc/internal/MetadataApplierImpl.java +++ b/core/src/main/java/io/grpc/internal/MetadataApplierImpl.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.CallCredentials.MetadataApplier; import io.grpc.CallOptions; import io.grpc.ClientStreamTracer; @@ -28,7 +29,6 @@ import io.grpc.MethodDescriptor; import io.grpc.Status; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; final class MetadataApplierImpl extends MetadataApplier { private final ClientTransport transport; diff --git a/core/src/main/java/io/grpc/internal/MigratingThreadDeframer.java b/core/src/main/java/io/grpc/internal/MigratingThreadDeframer.java index c3342556c9f..e4f499ab483 100644 --- a/core/src/main/java/io/grpc/internal/MigratingThreadDeframer.java +++ b/core/src/main/java/io/grpc/internal/MigratingThreadDeframer.java @@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkNotNull; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Decompressor; import io.perfmark.Link; import io.perfmark.PerfMark; @@ -26,7 +27,6 @@ import java.io.InputStream; import java.util.ArrayDeque; import java.util.Queue; -import javax.annotation.concurrent.GuardedBy; /** * A deframer that moves decoding between the transport and app threads based on which is more diff --git a/core/src/main/java/io/grpc/internal/RetriableStream.java b/core/src/main/java/io/grpc/internal/RetriableStream.java index ba9424ea25c..85d7bc86584 100644 --- a/core/src/main/java/io/grpc/internal/RetriableStream.java +++ b/core/src/main/java/io/grpc/internal/RetriableStream.java @@ -22,6 +22,8 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Objects; +import com.google.errorprone.annotations.CheckReturnValue; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Attributes; import io.grpc.ClientStreamTracer; import io.grpc.Compressor; @@ -47,9 +49,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import javax.annotation.CheckForNull; -import javax.annotation.CheckReturnValue; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; /** A logical {@link ClientStream} that is retriable. */ abstract class RetriableStream implements ClientStream { diff --git a/core/src/main/java/io/grpc/internal/ServerCallImpl.java b/core/src/main/java/io/grpc/internal/ServerCallImpl.java index dda36258e7c..e224384ce8f 100644 --- a/core/src/main/java/io/grpc/internal/ServerCallImpl.java +++ b/core/src/main/java/io/grpc/internal/ServerCallImpl.java @@ -373,10 +373,10 @@ private void closedInternal(Status status) { } else { call.cancelled = true; listener.onCancel(); - // The status will not have a cause in all failure scenarios but we want to make sure + // The status will not have a cause in all failure scenarios, but we want to make sure // we always cancel the context with one to keep the context cancelled state consistent. - cancelCause = InternalStatus.asRuntimeException( - Status.CANCELLED.withDescription("RPC cancelled"), null, false); + cancelCause = InternalStatus.asRuntimeExceptionWithoutStacktrace( + Status.CANCELLED.withDescription("RPC cancelled"), null); } } finally { // Cancel context after delivering RPC closure notification to allow the application to diff --git a/core/src/main/java/io/grpc/internal/ServerImpl.java b/core/src/main/java/io/grpc/internal/ServerImpl.java index cec2a13a301..dc0709e1fb8 100644 --- a/core/src/main/java/io/grpc/internal/ServerImpl.java +++ b/core/src/main/java/io/grpc/internal/ServerImpl.java @@ -31,6 +31,7 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Attributes; import io.grpc.BinaryLog; import io.grpc.CompressorRegistry; @@ -75,7 +76,6 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; -import javax.annotation.concurrent.GuardedBy; /** * Default implementation of {@link io.grpc.Server}, for creation by transports. @@ -887,8 +887,8 @@ private void closedInternal(final Status status) { // failed status has an exception we will create one here if needed. Throwable cancelCause = status.getCause(); if (cancelCause == null) { - cancelCause = InternalStatus.asRuntimeException( - Status.CANCELLED.withDescription("RPC cancelled"), null, false); + cancelCause = InternalStatus.asRuntimeExceptionWithoutStacktrace( + Status.CANCELLED.withDescription("RPC cancelled"), null); } // The callExecutor might be busy doing user work. To avoid waiting, use an executor that diff --git a/core/src/main/java/io/grpc/internal/SpiffeUtil.java b/core/src/main/java/io/grpc/internal/SpiffeUtil.java index 57e201d19ba..44ef343b6dc 100644 --- a/core/src/main/java/io/grpc/internal/SpiffeUtil.java +++ b/core/src/main/java/io/grpc/internal/SpiffeUtil.java @@ -23,13 +23,12 @@ import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.io.Files; import java.io.ByteArrayInputStream; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; @@ -188,8 +187,8 @@ public static SpiffeBundle loadTrustBundleFromFile(String trustBundleFile) throw } private static Map readTrustDomainsFromFile(String filePath) throws IOException { - Path path = Paths.get(checkNotNull(filePath, "trustBundleFile")); - String json = new String(Files.readAllBytes(path), StandardCharsets.UTF_8); + File file = new File(checkNotNull(filePath, "trustBundleFile")); + String json = new String(Files.toByteArray(file), StandardCharsets.UTF_8); Object jsonObject = JsonParser.parse(json); if (!(jsonObject instanceof Map)) { throw new IllegalArgumentException( diff --git a/core/src/main/java/io/grpc/internal/TransportFrameUtil.java b/core/src/main/java/io/grpc/internal/TransportFrameUtil.java index f3c32416426..3bd7ee72239 100644 --- a/core/src/main/java/io/grpc/internal/TransportFrameUtil.java +++ b/core/src/main/java/io/grpc/internal/TransportFrameUtil.java @@ -19,13 +19,13 @@ import static java.nio.charset.StandardCharsets.US_ASCII; import com.google.common.io.BaseEncoding; +import com.google.errorprone.annotations.CheckReturnValue; import io.grpc.InternalMetadata; import io.grpc.Metadata; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.logging.Logger; -import javax.annotation.CheckReturnValue; /** * Utility functions for transport layer framing. diff --git a/core/src/test/java/io/grpc/internal/ConcurrentTimeProviderTest.java b/core/src/test/java/io/grpc/internal/ConcurrentTimeProviderTest.java index a02cb6a6e42..7983530456c 100644 --- a/core/src/test/java/io/grpc/internal/ConcurrentTimeProviderTest.java +++ b/core/src/test/java/io/grpc/internal/ConcurrentTimeProviderTest.java @@ -18,7 +18,6 @@ import static com.google.common.truth.Truth.assertThat; -import java.time.Instant; import java.util.concurrent.TimeUnit; import org.junit.Test; import org.junit.runner.RunWith; @@ -36,10 +35,8 @@ public void testConcurrentCurrentTimeNanos() { // Get the current time from the ConcurrentTimeProvider long actualTimeNanos = concurrentTimeProvider.currentTimeNanos(); - // Get the current time from Instant for comparison - Instant instantNow = Instant.now(); - long expectedTimeNanos = TimeUnit.SECONDS.toNanos(instantNow.getEpochSecond()) - + instantNow.getNano(); + // Get the current time from System for comparison + long expectedTimeNanos = TimeUnit.MILLISECONDS.toNanos(System.currentTimeMillis()); // Validate the time returned is close to the expected value within a tolerance // (i,e 10 millisecond tolerance in nanoseconds). diff --git a/core/src/test/java/io/grpc/internal/InstantTimeProviderTest.java b/core/src/test/java/io/grpc/internal/InstantTimeProviderTest.java index 46d1891cbb9..ac9a02fa936 100644 --- a/core/src/test/java/io/grpc/internal/InstantTimeProviderTest.java +++ b/core/src/test/java/io/grpc/internal/InstantTimeProviderTest.java @@ -20,6 +20,7 @@ import java.time.Instant; import java.util.concurrent.TimeUnit; +import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -28,6 +29,7 @@ * Unit tests for {@link InstantTimeProvider}. */ @RunWith(JUnit4.class) +@IgnoreJRERequirement public class InstantTimeProviderTest { @Test public void testInstantCurrentTimeNanos() throws Exception { diff --git a/core/src/test/java/io/grpc/internal/ManagedChannelImplBuilderTest.java b/core/src/test/java/io/grpc/internal/ManagedChannelImplBuilderTest.java index ddef7ef546f..cf131a79d87 100644 --- a/core/src/test/java/io/grpc/internal/ManagedChannelImplBuilderTest.java +++ b/core/src/test/java/io/grpc/internal/ManagedChannelImplBuilderTest.java @@ -764,6 +764,16 @@ public void disableNameResolverServiceConfig() { assertThat(builder.lookUpServiceConfig).isFalse(); } + @Test + public void setNameResolverExtArgs() { + assertThat(builder.nameResolverCustomArgs) + .isNull(); + + NameResolver.Args.Key testKey = NameResolver.Args.Key.create("test-key"); + builder.setNameResolverArg(testKey, 42); + assertThat(builder.nameResolverCustomArgs.get(testKey)).isEqualTo(42); + } + @Test public void metricSinks() { MetricSink mocksink = mock(MetricSink.class); diff --git a/core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java b/core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java index 535086716bd..98900cecf2b 100644 --- a/core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java +++ b/core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java @@ -57,6 +57,7 @@ import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.SettableFuture; @@ -204,6 +205,8 @@ public class ManagedChannelImplTest { .setServiceConfigParser(mock(NameResolver.ServiceConfigParser.class)) .setScheduledExecutorService(new FakeClock().getScheduledExecutorService()) .build(); + private static final NameResolver.Args.Key TEST_RESOLVER_CUSTOM_ARG_KEY = + NameResolver.Args.Key.create("test-key"); private URI expectedUri; private final SocketAddress socketAddress = @@ -1199,8 +1202,10 @@ public void addressResolutionError_noPriorNameResolution_usesDefaultServiceConfi // config simply gets ignored and not gets reassigned. resolver.resolved(); timer.forwardNanos(1234); - assertThat(getStats(channel).channelTrace.events.stream().filter( - event -> event.description.equals("Service config changed")).count()).isEqualTo(0); + assertThat(Iterables.filter( + getStats(channel).channelTrace.events, + event -> event.description.equals("Service config changed"))) + .isEmpty(); } @Test @@ -4268,13 +4273,18 @@ public String getDefaultScheme() { return "fake"; } }; - channelBuilder.nameResolverFactory(factory).proxyDetector(neverProxy); + channelBuilder + .nameResolverFactory(factory) + .proxyDetector(neverProxy) + .setNameResolverArg(TEST_RESOLVER_CUSTOM_ARG_KEY, "test-value"); + createChannel(); NameResolver.Args args = capturedArgs.get(); assertThat(args).isNotNull(); assertThat(args.getDefaultPort()).isEqualTo(DEFAULT_PORT); assertThat(args.getProxyDetector()).isSameInstanceAs(neverProxy); + assertThat(args.getArg(TEST_RESOLVER_CUSTOM_ARG_KEY)).isEqualTo("test-value"); verify(offloadExecutor, never()).execute(any(Runnable.class)); args.getOffloadExecutor() diff --git a/core/src/test/java/io/grpc/internal/SpiffeUtilTest.java b/core/src/test/java/io/grpc/internal/SpiffeUtilTest.java index 244539501a6..d5155728936 100644 --- a/core/src/test/java/io/grpc/internal/SpiffeUtilTest.java +++ b/core/src/test/java/io/grpc/internal/SpiffeUtilTest.java @@ -22,15 +22,16 @@ import static org.junit.Assert.assertTrue; import com.google.common.base.Optional; +import com.google.common.io.ByteStreams; import io.grpc.internal.SpiffeUtil.SpiffeBundle; import io.grpc.internal.SpiffeUtil.SpiffeId; import io.grpc.testing.TlsTesting; import io.grpc.util.CertificateUtils; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.InputStream; -import java.nio.file.Files; -import java.nio.file.NoSuchFileException; -import java.nio.file.Path; -import java.nio.file.StandardCopyOption; +import java.io.OutputStream; import java.security.cert.X509Certificate; import java.util.Arrays; import java.util.Collection; @@ -247,12 +248,14 @@ public void setUp() throws Exception { } private String copyFileToTmp(String fileName) throws Exception { - Path tempFilePath = tempFolder.newFile(fileName).toPath(); + File tempFile = tempFolder.newFile(fileName); try (InputStream resourceStream = SpiffeUtilTest.class.getClassLoader() - .getResourceAsStream(TEST_DIRECTORY_PREFIX + fileName)) { - Files.copy(resourceStream, tempFilePath, StandardCopyOption.REPLACE_EXISTING); + .getResourceAsStream(TEST_DIRECTORY_PREFIX + fileName); + OutputStream fileStream = new FileOutputStream(tempFile)) { + ByteStreams.copy(resourceStream, fileStream); + fileStream.flush(); } - return tempFilePath.toString(); + return tempFile.toString(); } @Test @@ -358,9 +361,11 @@ public void loadTrustBundleFromFileParameterValidityTest() { NullPointerException npe = assertThrows(NullPointerException.class, () -> SpiffeUtil .loadTrustBundleFromFile(null)); assertEquals("trustBundleFile", npe.getMessage()); - NoSuchFileException nsfe = assertThrows(NoSuchFileException.class, () -> SpiffeUtil + FileNotFoundException nsfe = assertThrows(FileNotFoundException.class, () -> SpiffeUtil .loadTrustBundleFromFile("i_do_not_exist")); - assertEquals("i_do_not_exist", nsfe.getMessage()); + assertTrue( + "Did not contain expected substring: " + nsfe.getMessage(), + nsfe.getMessage().contains("i_do_not_exist")); } } -} \ No newline at end of file +} diff --git a/cronet/build.gradle b/cronet/build.gradle index 3252a9d249b..1a327f9f966 100644 --- a/cronet/build.gradle +++ b/cronet/build.gradle @@ -8,7 +8,6 @@ description = "gRPC: Cronet Android" repositories { google() - mavenCentral() } android { diff --git a/cronet/src/main/java/io/grpc/cronet/CronetClientStream.java b/cronet/src/main/java/io/grpc/cronet/CronetClientStream.java index 9ae97652316..95adb65ec40 100644 --- a/cronet/src/main/java/io/grpc/cronet/CronetClientStream.java +++ b/cronet/src/main/java/io/grpc/cronet/CronetClientStream.java @@ -25,6 +25,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.common.io.BaseEncoding; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Attributes; import io.grpc.CallOptions; import io.grpc.InternalMetadata; @@ -50,7 +51,6 @@ import java.util.Map; import java.util.concurrent.Executor; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; import org.chromium.net.BidirectionalStream; import org.chromium.net.CronetException; import org.chromium.net.UrlResponseInfo; diff --git a/cronet/src/main/java/io/grpc/cronet/CronetClientTransport.java b/cronet/src/main/java/io/grpc/cronet/CronetClientTransport.java index b0b18620d0c..465df8b2cc9 100644 --- a/cronet/src/main/java/io/grpc/cronet/CronetClientTransport.java +++ b/cronet/src/main/java/io/grpc/cronet/CronetClientTransport.java @@ -19,6 +19,7 @@ import com.google.common.base.Preconditions; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Attributes; import io.grpc.CallOptions; import io.grpc.ClientStreamTracer; @@ -42,7 +43,6 @@ import java.util.Set; import java.util.concurrent.Executor; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; /** * A cronet-based {@link ConnectionClientTransport} implementation. diff --git a/examples/android/clientcache/app/build.gradle b/examples/android/clientcache/app/build.gradle index d279155b64e..7700b2248eb 100644 --- a/examples/android/clientcache/app/build.gradle +++ b/examples/android/clientcache/app/build.gradle @@ -34,7 +34,7 @@ android { protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.25.1' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -54,12 +54,12 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.0.0' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION implementation 'org.apache.tomcat:annotations-api:6.0.53' testImplementation 'junit:junit:4.13.2' testImplementation 'com.google.truth:truth:1.1.5' - testImplementation 'io.grpc:grpc-testing:1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION + testImplementation 'io.grpc:grpc-testing:1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION } diff --git a/examples/android/helloworld/app/build.gradle b/examples/android/helloworld/app/build.gradle index d56a447377b..0fb396bbe39 100644 --- a/examples/android/helloworld/app/build.gradle +++ b/examples/android/helloworld/app/build.gradle @@ -32,7 +32,7 @@ android { protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.25.1' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -52,8 +52,8 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.0.0' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION implementation 'org.apache.tomcat:annotations-api:6.0.53' } diff --git a/examples/android/routeguide/app/build.gradle b/examples/android/routeguide/app/build.gradle index 1dceb21b5c9..1a8209913a2 100644 --- a/examples/android/routeguide/app/build.gradle +++ b/examples/android/routeguide/app/build.gradle @@ -32,7 +32,7 @@ android { protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.25.1' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -52,8 +52,8 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.0.0' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION implementation 'org.apache.tomcat:annotations-api:6.0.53' } diff --git a/examples/android/strictmode/app/build.gradle b/examples/android/strictmode/app/build.gradle index 2bb696027fd..02b17c189f9 100644 --- a/examples/android/strictmode/app/build.gradle +++ b/examples/android/strictmode/app/build.gradle @@ -33,7 +33,7 @@ android { protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.25.1' } plugins { - grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION + grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION } } generateProtoTasks { @@ -53,8 +53,8 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.0.0' // You need to build grpc-java to obtain these libraries below. - implementation 'io.grpc:grpc-okhttp:1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-protobuf-lite:1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION - implementation 'io.grpc:grpc-stub:1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-okhttp:1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-protobuf-lite:1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION + implementation 'io.grpc:grpc-stub:1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION implementation 'org.apache.tomcat:annotations-api:6.0.53' } diff --git a/examples/build.gradle b/examples/build.gradle index 756a9c47bb1..d4991f02f43 100644 --- a/examples/build.gradle +++ b/examples/build.gradle @@ -7,8 +7,6 @@ plugins { } repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" } mavenCentral() mavenLocal() } @@ -23,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.5' def protocVersion = protobufVersion @@ -109,6 +107,7 @@ createStartScripts('io.grpc.examples.keepalive.KeepAliveClient') createStartScripts('io.grpc.examples.keepalive.KeepAliveServer') createStartScripts('io.grpc.examples.loadbalance.LoadBalanceClient') createStartScripts('io.grpc.examples.loadbalance.LoadBalanceServer') +createStartScripts('io.grpc.examples.manualflowcontrol.BidiBlockingClient') createStartScripts('io.grpc.examples.manualflowcontrol.ManualFlowControlClient') createStartScripts('io.grpc.examples.manualflowcontrol.ManualFlowControlServer') createStartScripts('io.grpc.examples.multiplex.MultiplexingServer') diff --git a/examples/example-alts/build.gradle b/examples/example-alts/build.gradle index f0dc0bd8850..17b2568c7ea 100644 --- a/examples/example-alts/build.gradle +++ b/examples/example-alts/build.gradle @@ -7,9 +7,6 @@ plugins { } repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" - } mavenCentral() mavenLocal() } @@ -24,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' dependencies { diff --git a/examples/example-alts/settings.gradle b/examples/example-alts/settings.gradle index 273558dd9cf..c665ff96674 100644 --- a/examples/example-alts/settings.gradle +++ b/examples/example-alts/settings.gradle @@ -1,8 +1,5 @@ pluginManagement { repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" - } gradlePluginPortal() } } diff --git a/examples/example-debug/build.gradle b/examples/example-debug/build.gradle index 7cd3b5de38e..7701465dee2 100644 --- a/examples/example-debug/build.gradle +++ b/examples/example-debug/build.gradle @@ -9,8 +9,6 @@ plugins { } repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" } mavenCentral() mavenLocal() } @@ -25,7 +23,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.5' dependencies { diff --git a/examples/example-debug/pom.xml b/examples/example-debug/pom.xml index 2239bc03d5a..2976782a5d7 100644 --- a/examples/example-debug/pom.xml +++ b/examples/example-debug/pom.xml @@ -6,13 +6,13 @@ jar - 1.70.0-SNAPSHOT + 1.71.0-SNAPSHOT example-debug https://github.com/grpc/grpc-java UTF-8 - 1.70.0-SNAPSHOT + 1.71.0-SNAPSHOT 3.25.5 1.8 diff --git a/examples/example-dualstack/build.gradle b/examples/example-dualstack/build.gradle index 875bdfda623..a0f29660afc 100644 --- a/examples/example-dualstack/build.gradle +++ b/examples/example-dualstack/build.gradle @@ -9,8 +9,6 @@ plugins { } repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" } mavenCentral() mavenLocal() } @@ -25,7 +23,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.5' dependencies { diff --git a/examples/example-dualstack/pom.xml b/examples/example-dualstack/pom.xml index 3c7f14cacde..99f98cc5b48 100644 --- a/examples/example-dualstack/pom.xml +++ b/examples/example-dualstack/pom.xml @@ -6,13 +6,13 @@ jar - 1.70.0-SNAPSHOT + 1.71.0-SNAPSHOT example-dualstack https://github.com/grpc/grpc-java UTF-8 - 1.70.0-SNAPSHOT + 1.71.0-SNAPSHOT 3.25.5 1.8 diff --git a/examples/example-dualstack/settings.gradle b/examples/example-dualstack/settings.gradle index 0aae8f7304e..49a762696f7 100644 --- a/examples/example-dualstack/settings.gradle +++ b/examples/example-dualstack/settings.gradle @@ -1,8 +1,5 @@ pluginManagement { repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" - } gradlePluginPortal() } } diff --git a/examples/example-gauth/build.gradle b/examples/example-gauth/build.gradle index 3ff0284c5a1..aea626a5193 100644 --- a/examples/example-gauth/build.gradle +++ b/examples/example-gauth/build.gradle @@ -7,9 +7,6 @@ plugins { } repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" - } mavenCentral() mavenLocal() } @@ -24,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.5' def protocVersion = protobufVersion diff --git a/examples/example-gauth/pom.xml b/examples/example-gauth/pom.xml index 0aeedccbda3..00e7ee0e3ad 100644 --- a/examples/example-gauth/pom.xml +++ b/examples/example-gauth/pom.xml @@ -6,13 +6,13 @@ jar - 1.70.0-SNAPSHOT + 1.71.0-SNAPSHOT example-gauth https://github.com/grpc/grpc-java UTF-8 - 1.70.0-SNAPSHOT + 1.71.0-SNAPSHOT 3.25.5 1.8 diff --git a/examples/example-gauth/settings.gradle b/examples/example-gauth/settings.gradle index 273558dd9cf..c665ff96674 100644 --- a/examples/example-gauth/settings.gradle +++ b/examples/example-gauth/settings.gradle @@ -1,8 +1,5 @@ pluginManagement { repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" - } gradlePluginPortal() } } diff --git a/examples/example-gcp-csm-observability/build.gradle b/examples/example-gcp-csm-observability/build.gradle index c72f1ba9753..5ccb5bb0d3a 100644 --- a/examples/example-gcp-csm-observability/build.gradle +++ b/examples/example-gcp-csm-observability/build.gradle @@ -8,9 +8,6 @@ plugins { } repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" - } mavenCentral() mavenLocal() } @@ -25,7 +22,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' def openTelemetryVersion = '1.40.0' def openTelemetryPrometheusVersion = '1.40.0-alpha' diff --git a/examples/example-gcp-observability/build.gradle b/examples/example-gcp-observability/build.gradle index 5199105baae..3c7b0587e8f 100644 --- a/examples/example-gcp-observability/build.gradle +++ b/examples/example-gcp-observability/build.gradle @@ -8,9 +8,6 @@ plugins { } repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" - } mavenCentral() mavenLocal() } @@ -25,7 +22,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' dependencies { diff --git a/examples/example-hostname/build.gradle b/examples/example-hostname/build.gradle index 784b0c71a47..9eb5f38c364 100644 --- a/examples/example-hostname/build.gradle +++ b/examples/example-hostname/build.gradle @@ -7,8 +7,6 @@ plugins { } repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" } mavenCentral() mavenLocal() } @@ -23,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.5' dependencies { diff --git a/examples/example-hostname/pom.xml b/examples/example-hostname/pom.xml index b22318f4d53..d7ac43e79ae 100644 --- a/examples/example-hostname/pom.xml +++ b/examples/example-hostname/pom.xml @@ -6,13 +6,13 @@ jar - 1.70.0-SNAPSHOT + 1.71.0-SNAPSHOT example-hostname https://github.com/grpc/grpc-java UTF-8 - 1.70.0-SNAPSHOT + 1.71.0-SNAPSHOT 3.25.5 1.8 diff --git a/examples/example-jwt-auth/build.gradle b/examples/example-jwt-auth/build.gradle index ba7aeb05b19..64ea928456b 100644 --- a/examples/example-jwt-auth/build.gradle +++ b/examples/example-jwt-auth/build.gradle @@ -7,9 +7,7 @@ plugins { } repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" - } + mavenCentral() mavenLocal() } @@ -23,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.5' def protocVersion = protobufVersion diff --git a/examples/example-jwt-auth/pom.xml b/examples/example-jwt-auth/pom.xml index f90da62fcd8..6c1e172b2e0 100644 --- a/examples/example-jwt-auth/pom.xml +++ b/examples/example-jwt-auth/pom.xml @@ -7,13 +7,13 @@ jar - 1.70.0-SNAPSHOT + 1.71.0-SNAPSHOT example-jwt-auth https://github.com/grpc/grpc-java UTF-8 - 1.70.0-SNAPSHOT + 1.71.0-SNAPSHOT 3.25.5 3.25.5 diff --git a/examples/example-jwt-auth/settings.gradle b/examples/example-jwt-auth/settings.gradle index 273558dd9cf..c665ff96674 100644 --- a/examples/example-jwt-auth/settings.gradle +++ b/examples/example-jwt-auth/settings.gradle @@ -1,8 +1,5 @@ pluginManagement { repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" - } gradlePluginPortal() } } diff --git a/examples/example-oauth/build.gradle b/examples/example-oauth/build.gradle index 6e07cbc7447..4de1183e0d7 100644 --- a/examples/example-oauth/build.gradle +++ b/examples/example-oauth/build.gradle @@ -7,9 +7,7 @@ plugins { } repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" - } + mavenCentral() mavenLocal() } @@ -23,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protobufVersion = '3.25.5' def protocVersion = protobufVersion diff --git a/examples/example-oauth/pom.xml b/examples/example-oauth/pom.xml index 22d42abf642..f01b362347a 100644 --- a/examples/example-oauth/pom.xml +++ b/examples/example-oauth/pom.xml @@ -7,13 +7,13 @@ jar - 1.70.0-SNAPSHOT + 1.71.0-SNAPSHOT example-oauth https://github.com/grpc/grpc-java UTF-8 - 1.70.0-SNAPSHOT + 1.71.0-SNAPSHOT 3.25.5 3.25.5 diff --git a/examples/example-oauth/settings.gradle b/examples/example-oauth/settings.gradle index 273558dd9cf..c665ff96674 100644 --- a/examples/example-oauth/settings.gradle +++ b/examples/example-oauth/settings.gradle @@ -1,8 +1,5 @@ pluginManagement { repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" - } gradlePluginPortal() } } diff --git a/examples/example-opentelemetry/build.gradle b/examples/example-opentelemetry/build.gradle index 5c1e419c82e..2e0cbfbe0b6 100644 --- a/examples/example-opentelemetry/build.gradle +++ b/examples/example-opentelemetry/build.gradle @@ -7,9 +7,6 @@ plugins { } repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" - } mavenCentral() mavenLocal() } @@ -24,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' def openTelemetryVersion = '1.40.0' def openTelemetryPrometheusVersion = '1.40.0-alpha' diff --git a/examples/example-orca/build.gradle b/examples/example-orca/build.gradle index babd0c7d18e..ffa8295f849 100644 --- a/examples/example-orca/build.gradle +++ b/examples/example-orca/build.gradle @@ -7,8 +7,6 @@ plugins { } repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" } mavenCentral() mavenLocal() } @@ -18,7 +16,7 @@ java { targetCompatibility = JavaVersion.VERSION_1_8 } -def grpcVersion = '1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' dependencies { diff --git a/examples/example-reflection/build.gradle b/examples/example-reflection/build.gradle index d82f5ecda7e..8c885d9cb99 100644 --- a/examples/example-reflection/build.gradle +++ b/examples/example-reflection/build.gradle @@ -7,8 +7,6 @@ plugins { } repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" } mavenCentral() mavenLocal() } @@ -18,7 +16,7 @@ java { targetCompatibility = JavaVersion.VERSION_1_8 } -def grpcVersion = '1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' dependencies { diff --git a/examples/example-servlet/build.gradle b/examples/example-servlet/build.gradle index 50b9d47632c..163276aec10 100644 --- a/examples/example-servlet/build.gradle +++ b/examples/example-servlet/build.gradle @@ -6,8 +6,7 @@ plugins { } repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" } + mavenCentral() mavenLocal() } @@ -16,7 +15,7 @@ java { targetCompatibility = JavaVersion.VERSION_1_8 } -def grpcVersion = '1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' dependencies { diff --git a/examples/example-servlet/settings.gradle b/examples/example-servlet/settings.gradle index 273558dd9cf..c665ff96674 100644 --- a/examples/example-servlet/settings.gradle +++ b/examples/example-servlet/settings.gradle @@ -1,8 +1,5 @@ pluginManagement { repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" - } gradlePluginPortal() } } diff --git a/examples/example-tls/build.gradle b/examples/example-tls/build.gradle index 2d61862700b..87e37c5a3b1 100644 --- a/examples/example-tls/build.gradle +++ b/examples/example-tls/build.gradle @@ -7,9 +7,6 @@ plugins { } repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" - } mavenCentral() mavenLocal() } @@ -24,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' dependencies { diff --git a/examples/example-tls/pom.xml b/examples/example-tls/pom.xml index e16ce1018a8..ade33ee8769 100644 --- a/examples/example-tls/pom.xml +++ b/examples/example-tls/pom.xml @@ -6,13 +6,13 @@ jar - 1.70.0-SNAPSHOT + 1.71.0-SNAPSHOT example-tls https://github.com/grpc/grpc-java UTF-8 - 1.70.0-SNAPSHOT + 1.71.0-SNAPSHOT 3.25.5 1.8 diff --git a/examples/example-tls/settings.gradle b/examples/example-tls/settings.gradle index 273558dd9cf..c665ff96674 100644 --- a/examples/example-tls/settings.gradle +++ b/examples/example-tls/settings.gradle @@ -1,8 +1,5 @@ pluginManagement { repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" - } gradlePluginPortal() } } diff --git a/examples/example-xds/build.gradle b/examples/example-xds/build.gradle index bb404bdb07c..ef1bc185816 100644 --- a/examples/example-xds/build.gradle +++ b/examples/example-xds/build.gradle @@ -7,8 +7,6 @@ plugins { } repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" } mavenCentral() mavenLocal() } @@ -23,7 +21,7 @@ java { // Feel free to delete the comment at the next line. It is just for safely // updating the version in our release process. -def grpcVersion = '1.70.0-SNAPSHOT' // CURRENT_GRPC_VERSION +def grpcVersion = '1.71.0-SNAPSHOT' // CURRENT_GRPC_VERSION def protocVersion = '3.25.5' dependencies { diff --git a/examples/pom.xml b/examples/pom.xml index 04cd792cd3e..6370ce7d56a 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -6,13 +6,13 @@ jar - 1.70.0-SNAPSHOT + 1.71.0-SNAPSHOT examples https://github.com/grpc/grpc-java UTF-8 - 1.70.0-SNAPSHOT + 1.71.0-SNAPSHOT 3.25.5 3.25.5 diff --git a/examples/settings.gradle b/examples/settings.gradle index 0473750a54f..dadd24b1c0f 100644 --- a/examples/settings.gradle +++ b/examples/settings.gradle @@ -1,8 +1,5 @@ pluginManagement { repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" - } gradlePluginPortal() } } diff --git a/examples/src/main/java/io/grpc/examples/header/HeaderClientInterceptor.java b/examples/src/main/java/io/grpc/examples/header/HeaderClientInterceptor.java index b9a73931299..2a60eeda6c4 100644 --- a/examples/src/main/java/io/grpc/examples/header/HeaderClientInterceptor.java +++ b/examples/src/main/java/io/grpc/examples/header/HeaderClientInterceptor.java @@ -52,7 +52,7 @@ public void start(Listener responseListener, Metadata headers) { public void onHeaders(Metadata headers) { /** * if you don't need receive header from server, - * you can use {@link io.grpc.stub.MetadataUtils#attachHeaders} + * you can use {@link io.grpc.stub.MetadataUtils#newAttachHeadersInterceptor} * directly to send header */ logger.info("header received from server:" + headers); diff --git a/examples/src/main/java/io/grpc/examples/manualflowcontrol/BidiBlockingClient.java b/examples/src/main/java/io/grpc/examples/manualflowcontrol/BidiBlockingClient.java new file mode 100644 index 00000000000..902d46c8cc6 --- /dev/null +++ b/examples/src/main/java/io/grpc/examples/manualflowcontrol/BidiBlockingClient.java @@ -0,0 +1,286 @@ +/* + * Copyright 2023 The gRPC Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc.examples.manualflowcontrol; + +import com.google.protobuf.ByteString; +import io.grpc.Grpc; +import io.grpc.InsecureChannelCredentials; +import io.grpc.ManagedChannel; +import io.grpc.StatusException; +import io.grpc.examples.manualflowcontrol.StreamingGreeterGrpc.StreamingGreeterBlockingV2Stub; +import io.grpc.stub.BlockingClientCall; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; + + +/** + * A class that tries multiple ways to do blocking bidi streaming + * communication with an echo server + */ +public class BidiBlockingClient { + + private static final Logger logger = Logger.getLogger(BidiBlockingClient.class.getName()); + + /** + * Greet server. If provided, the first element of {@code args} is the name to use in the + * greeting. The second argument is the target server. You can see the multiplexing in the server + * logs. + */ + public static void main(String[] args) throws Exception { + System.setProperty("java.util.logging.SimpleFormatter.format", "%1$tH:%1$tM:%1$tS %5$s%6$s%n"); + + // Access a service running on the local machine on port 50051 + String target = "localhost:50051"; + // Allow passing in the user and target strings as command line arguments + if (args.length > 0) { + if ("--help".equals(args[0])) { + System.err.println("Usage: [target]\n"); + System.err.println(" target The server to connect to. Defaults to " + target); + System.exit(1); + } + target = args[0]; + } + + // Create a communication channel to the server, known as a Channel. Channels are thread-safe + // and reusable. It is common to create channels at the beginning of your application and reuse + // them until the application shuts down. + // + // For the example we use plaintext insecure credentials to avoid needing TLS certificates. To + // use TLS, use TlsChannelCredentials instead. + ManagedChannel channel = Grpc.newChannelBuilder(target, InsecureChannelCredentials.create()) + .build(); + StreamingGreeterBlockingV2Stub blockingStub = StreamingGreeterGrpc.newBlockingV2Stub(channel); + List echoInput = names(); + try { + long start = System.currentTimeMillis(); + List twoThreadResult = useTwoThreads(blockingStub, echoInput); + long finish = System.currentTimeMillis(); + + System.out.println("The echo requests and results were:"); + printResultMessage("Input", echoInput, 0L); + printResultMessage("2 threads", twoThreadResult, finish - start); + } finally { + // ManagedChannels use resources like threads and TCP connections. To prevent leaking these + // resources the channel should be shut down when it will no longer be used. If it may be used + // again leave it running. + channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS); + } + } + + private static void printResultMessage(String type, List result, long millis) { + String msg = String.format("%-32s: %2d, %.3f sec", type, result.size(), millis/1000.0); + logger.info(msg); + } + + private static void logMethodStart(String method) { + logger.info("--------------------- Starting to process using method: " + method); + } + + /** + * Create 2 threads, one that writes all values, and one that reads until the stream closes. + */ + private static List useTwoThreads(StreamingGreeterBlockingV2Stub blockingStub, + List valuesToWrite) throws InterruptedException { + logMethodStart("Two Threads"); + + List readValues = new ArrayList<>(); + final BlockingClientCall stream = blockingStub.sayHelloStreaming(); + + Thread reader = new Thread(null, + new Runnable() { + @Override + public void run() { + int count = 0; + try { + while (stream.hasNext()) { + readValues.add(stream.read().getMessage()); + if (++count % 10 == 0) { + logger.info("Finished " + count + " reads"); + } + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + stream.cancel("Interrupted", e); + } catch (StatusException e) { + logger.warning("Encountered error while reading: " + e); + } + } + },"reader"); + + Thread writer = new Thread(null, + new Runnable() { + @Override + public void run() { + ByteString padding = createPadding(); + int count = 0; + Iterator iterator = valuesToWrite.iterator(); + boolean hadProblem = false; + try { + while (iterator.hasNext()) { + if (!stream.write(HelloRequest.newBuilder().setName(iterator.next()).setPadding(padding) + .build())) { + logger.warning("Stream closed before writes completed"); + hadProblem = true; + break; + } + if (++count % 10 == 0) { + logger.info("Finished " + count + " writes"); + } + } + if (!hadProblem) { + logger.info("Completed writes"); + stream.halfClose(); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + stream.cancel("Interrupted", e); + } catch (StatusException e) { + logger.warning("Encountered error while writing: " + e); + } + } + }, "writer"); + + writer.start(); + reader.start(); + writer.join(); + reader.join(); + + return readValues; + } + + private static ByteString createPadding() { + int multiple = 50; + ByteBuffer data = ByteBuffer.allocate(1024 * multiple); + + for (int i = 0; i < multiple * 1024 / 4; i++) { + data.putInt(4 * i, 1111); + } + + return ByteString.copyFrom(data); + } + + + private static List names() { + return Arrays.asList( + "Sophia", + "Jackson", + "Emma", + "Aiden", + "Olivia", + "Lucas", + "Ava", + "Liam", + "Mia", + "Noah", + "Isabella", + "Ethan", + "Riley", + "Mason", + "Aria", + "Caden", + "Zoe", + "Oliver", + "Charlotte", + "Elijah", + "Lily", + "Grayson", + "Layla", + "Jacob", + "Amelia", + "Michael", + "Emily", + "Benjamin", + "Madelyn", + "Carter", + "Aubrey", + "James", + "Adalyn", + "Jayden", + "Madison", + "Logan", + "Chloe", + "Alexander", + "Harper", + "Caleb", + "Abigail", + "Ryan", + "Aaliyah", + "Luke", + "Avery", + "Daniel", + "Evelyn", + "Jack", + "Kaylee", + "William", + "Ella", + "Owen", + "Ellie", + "Gabriel", + "Scarlett", + "Matthew", + "Arianna", + "Connor", + "Hailey", + "Jayce", + "Nora", + "Isaac", + "Addison", + "Sebastian", + "Brooklyn", + "Henry", + "Hannah", + "Muhammad", + "Mila", + "Cameron", + "Leah", + "Wyatt", + "Elizabeth", + "Dylan", + "Sarah", + "Nathan", + "Eliana", + "Nicholas", + "Mackenzie", + "Julian", + "Peyton", + "Eli", + "Maria", + "Levi", + "Grace", + "Isaiah", + "Adeline", + "Landon", + "Elena", + "David", + "Anna", + "Christian", + "Victoria", + "Andrew", + "Camilla", + "Brayden", + "Lillian", + "John", + "Natalie", + "Lincoln" + ); + } +} diff --git a/examples/src/main/java/io/grpc/examples/manualflowcontrol/ManualFlowControlServer.java b/examples/src/main/java/io/grpc/examples/manualflowcontrol/ManualFlowControlServer.java index de8142596ea..3b7f980e08c 100644 --- a/examples/src/main/java/io/grpc/examples/manualflowcontrol/ManualFlowControlServer.java +++ b/examples/src/main/java/io/grpc/examples/manualflowcontrol/ManualFlowControlServer.java @@ -72,6 +72,7 @@ public void run() { // Give gRPC a StreamObserver that can observe and process incoming requests. return new StreamObserver() { + int cnt = 0; @Override public void onNext(HelloRequest request) { // Process the request and send a response or an error. @@ -81,7 +82,8 @@ public void onNext(HelloRequest request) { logger.info("--> " + name); // Simulate server "work" - Thread.sleep(100); + int sleepMillis = ++cnt % 20 == 0 ? 2000 : 100; + Thread.sleep(sleepMillis); // Send a response. String message = "Hello " + name; diff --git a/examples/src/main/proto/hello_streaming.proto b/examples/src/main/proto/hello_streaming.proto index 325b9093b0c..b4f0f5287dd 100644 --- a/examples/src/main/proto/hello_streaming.proto +++ b/examples/src/main/proto/hello_streaming.proto @@ -29,6 +29,7 @@ service StreamingGreeter { // The request message containing the user's name. message HelloRequest { string name = 1; + bytes padding = 2; } // The response message containing the greetings diff --git a/gae-interop-testing/gae-jdk8/build.gradle b/gae-interop-testing/gae-jdk8/build.gradle index a09a8e793c0..14abbc05a9b 100644 --- a/gae-interop-testing/gae-jdk8/build.gradle +++ b/gae-interop-testing/gae-jdk8/build.gradle @@ -14,10 +14,6 @@ buildscript { // Configuration for building - repositories { - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" } - } dependencies { classpath 'com.squareup.okhttp:okhttp:2.7.4' } @@ -33,13 +29,6 @@ plugins { description = 'gRPC: gae interop testing (jdk8)' -repositories { - // repositories for Jar's you access in your code - mavenLocal() - maven { // The google mirror is less flaky than mavenCentral() - url "https://maven-central.storage-download.googleapis.com/maven2/" } -} - dependencies { providedCompile group: 'javax.servlet', name: 'servlet-api', version:'2.5' runtimeOnly 'com.google.appengine:appengine-api-1.0-sdk:1.9.59' @@ -53,7 +42,11 @@ dependencies { implementation libraries.junit implementation libraries.protobuf.java runtimeOnly libraries.netty.tcnative, libraries.netty.tcnative.classes - signature libraries.signature.java + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } } tasks.named("compileJava").configure { diff --git a/gcp-csm-observability/build.gradle b/gcp-csm-observability/build.gradle index e29a56b1052..bda54ca8146 100644 --- a/gcp-csm-observability/build.gradle +++ b/gcp-csm-observability/build.gradle @@ -28,5 +28,9 @@ dependencies { libraries.opentelemetry.sdk.testing, libraries.assertj.core // opentelemetry.sdk.testing uses compileOnly for this dep - signature libraries.signature.java + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } } diff --git a/gcp-observability/build.gradle b/gcp-observability/build.gradle index f869bd61a76..c6d6fa28ddc 100644 --- a/gcp-observability/build.gradle +++ b/gcp-observability/build.gradle @@ -74,7 +74,11 @@ dependencies { exclude group: 'junit', module: 'junit' } - signature libraries.signature.java + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } } configureProtoCompilation() diff --git a/gcp-observability/interop/build.gradle b/gcp-observability/interop/build.gradle index 4a78c056eac..7e17624995a 100644 --- a/gcp-observability/interop/build.gradle +++ b/gcp-observability/interop/build.gradle @@ -10,7 +10,11 @@ dependencies { implementation project(':grpc-interop-testing'), project(':grpc-gcp-observability') - signature libraries.signature.java + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } } application { diff --git a/googleapis/build.gradle b/googleapis/build.gradle index 435e552d47d..3a7a3a2766a 100644 --- a/googleapis/build.gradle +++ b/googleapis/build.gradle @@ -21,5 +21,9 @@ dependencies { libraries.guava.jre // JRE required by transitive protobuf-java-util testImplementation testFixtures(project(':grpc-core')) - signature libraries.signature.java + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b9f9c5350e1..43ec3368b76 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -62,7 +62,7 @@ jetty-servlet10 = "org.eclipse.jetty:jetty-servlet:10.0.20" jsr305 = "com.google.code.findbugs:jsr305:3.0.2" junit = "junit:junit:4.13.2" # 2.17+ require Java 11+ (not mentioned in release notes) -lincheck = "org.jetbrains.kotlinx:lincheck:2.16" +lincheck = "org.jetbrains.kotlinx:lincheck-jvm:2.16" # Update notes / 2023-07-19 sergiitk: # Couldn't update to 5.4.0, updated to the last in 4.x line. Version 5.x breaks some tests. # Error log: https://github.com/grpc/grpc-java/pull/10359#issuecomment-1632834435 @@ -97,7 +97,7 @@ protobuf-javalite = { module = "com.google.protobuf:protobuf-javalite", version. protobuf-protoc = { module = "com.google.protobuf:protoc", version.ref = "protobuf" } re2j = "com.google.re2j:re2j:1.7" robolectric = "org.robolectric:robolectric:4.13" -signature-android = "net.sf.androidscents.signature:android-api-level-19:4.4.2_r4" +signature-android = "net.sf.androidscents.signature:android-api-level-21:5.0.1_r2" signature-java = "org.codehaus.mojo.signature:java18:1.0" # 11.0.0+ require Java 17+ tomcat-embed-core = "org.apache.tomcat.embed:tomcat-embed-core:10.1.31" diff --git a/grpclb/BUILD.bazel b/grpclb/BUILD.bazel index 2dd24bb52a2..902ae7f47d4 100644 --- a/grpclb/BUILD.bazel +++ b/grpclb/BUILD.bazel @@ -20,6 +20,7 @@ java_library( "@com_google_protobuf//:protobuf_java_util", "@io_grpc_grpc_proto//:grpclb_load_balancer_java_proto", artifact("com.google.code.findbugs:jsr305"), + artifact("com.google.errorprone:error_prone_annotations"), artifact("com.google.guava:guava"), ], ) diff --git a/grpclb/build.gradle b/grpclb/build.gradle index 93331053b09..3f67181372b 100644 --- a/grpclb/build.gradle +++ b/grpclb/build.gradle @@ -28,7 +28,11 @@ dependencies { project(':grpc-inprocess'), testFixtures(project(':grpc-core')) - signature libraries.signature.java + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } } configureProtoCompilation() diff --git a/grpclb/src/generated/main/grpc/io/grpc/lb/v1/LoadBalancerGrpc.java b/grpclb/src/generated/main/grpc/io/grpc/lb/v1/LoadBalancerGrpc.java index c96c5400aac..2a81dfe4ee5 100644 --- a/grpclb/src/generated/main/grpc/io/grpc/lb/v1/LoadBalancerGrpc.java +++ b/grpclb/src/generated/main/grpc/io/grpc/lb/v1/LoadBalancerGrpc.java @@ -60,6 +60,21 @@ public LoadBalancerStub newStub(io.grpc.Channel channel, io.grpc.CallOptions cal return LoadBalancerStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static LoadBalancerBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public LoadBalancerBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new LoadBalancerBlockingV2Stub(channel, callOptions); + } + }; + return LoadBalancerBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -147,6 +162,35 @@ public io.grpc.stub.StreamObserver balanceLoad /** * A stub to allow clients to do synchronous rpc calls to service LoadBalancer. */ + public static final class LoadBalancerBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private LoadBalancerBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected LoadBalancerBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new LoadBalancerBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * Bidirectional rpc to get a list of servers.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + balanceLoad() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getBalanceLoadMethod(), getCallOptions()); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service LoadBalancer. + */ public static final class LoadBalancerBlockingStub extends io.grpc.stub.AbstractBlockingStub { private LoadBalancerBlockingStub( diff --git a/grpclb/src/main/java/io/grpc/grpclb/GrpclbClientLoadRecorder.java b/grpclb/src/main/java/io/grpc/grpclb/GrpclbClientLoadRecorder.java index d27c485dc13..fe928263ef9 100644 --- a/grpclb/src/main/java/io/grpc/grpclb/GrpclbClientLoadRecorder.java +++ b/grpclb/src/main/java/io/grpc/grpclb/GrpclbClientLoadRecorder.java @@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkNotNull; +import com.google.errorprone.annotations.concurrent.GuardedBy; import com.google.protobuf.util.Timestamps; import io.grpc.ClientStreamTracer; import io.grpc.Metadata; @@ -29,7 +30,6 @@ import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicLongFieldUpdater; -import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.ThreadSafe; /** diff --git a/inprocess/build.gradle b/inprocess/build.gradle index edc97883b50..075968ccb9a 100644 --- a/inprocess/build.gradle +++ b/inprocess/build.gradle @@ -22,8 +22,16 @@ dependencies { testFixtures(project(':grpc-core')) testImplementation libraries.guava.testlib - signature libraries.signature.java - signature libraries.signature.android + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } + signature (libraries.signature.android) { + artifact { + extension = "signature" + } + } } tasks.named("javadoc").configure { diff --git a/inprocess/src/main/java/io/grpc/inprocess/AnonymousInProcessSocketAddress.java b/inprocess/src/main/java/io/grpc/inprocess/AnonymousInProcessSocketAddress.java index 5f6486e335d..089a9f12b02 100644 --- a/inprocess/src/main/java/io/grpc/inprocess/AnonymousInProcessSocketAddress.java +++ b/inprocess/src/main/java/io/grpc/inprocess/AnonymousInProcessSocketAddress.java @@ -18,11 +18,11 @@ import static com.google.common.base.Preconditions.checkState; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.ExperimentalApi; import java.io.IOException; import java.net.SocketAddress; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; /** * Custom SocketAddress class for {@link InProcessTransport}, for diff --git a/inprocess/src/main/java/io/grpc/inprocess/InProcessTransport.java b/inprocess/src/main/java/io/grpc/inprocess/InProcessTransport.java index eacf46ca4a2..39ebe6e0ab7 100644 --- a/inprocess/src/main/java/io/grpc/inprocess/InProcessTransport.java +++ b/inprocess/src/main/java/io/grpc/inprocess/InProcessTransport.java @@ -24,6 +24,8 @@ import com.google.common.io.ByteStreams; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; +import com.google.errorprone.annotations.CheckReturnValue; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Attributes; import io.grpc.CallOptions; import io.grpc.ClientStreamTracer; @@ -74,9 +76,7 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; -import javax.annotation.CheckReturnValue; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.ThreadSafe; @ThreadSafe diff --git a/interop-testing/build.gradle b/interop-testing/build.gradle index a85aec97adf..97e7c69533a 100644 --- a/interop-testing/build.gradle +++ b/interop-testing/build.gradle @@ -53,8 +53,16 @@ dependencies { libraries.mockito.core, libraries.okhttp - signature libraries.signature.java - signature libraries.signature.android + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } + signature (libraries.signature.android) { + artifact { + extension = "signature" + } + } } configureProtoCompilation() diff --git a/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/LoadBalancerStatsServiceGrpc.java b/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/LoadBalancerStatsServiceGrpc.java index 2f4dc69c0c6..f060a1308d8 100644 --- a/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/LoadBalancerStatsServiceGrpc.java +++ b/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/LoadBalancerStatsServiceGrpc.java @@ -94,6 +94,21 @@ public LoadBalancerStatsServiceStub newStub(io.grpc.Channel channel, io.grpc.Cal return LoadBalancerStatsServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static LoadBalancerStatsServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public LoadBalancerStatsServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new LoadBalancerStatsServiceBlockingV2Stub(channel, callOptions); + } + }; + return LoadBalancerStatsServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -214,6 +229,46 @@ public void getClientAccumulatedStats(io.grpc.testing.integration.Messages.LoadB * A service used to obtain stats for verifying LB behavior. * */ + public static final class LoadBalancerStatsServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private LoadBalancerStatsServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected LoadBalancerStatsServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new LoadBalancerStatsServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * Gets the backend distribution for RPCs sent by a test client.
+     * 
+ */ + public io.grpc.testing.integration.Messages.LoadBalancerStatsResponse getClientStats(io.grpc.testing.integration.Messages.LoadBalancerStatsRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getGetClientStatsMethod(), getCallOptions(), request); + } + + /** + *
+     * Gets the accumulated stats for RPCs sent by a test client.
+     * 
+ */ + public io.grpc.testing.integration.Messages.LoadBalancerAccumulatedStatsResponse getClientAccumulatedStats(io.grpc.testing.integration.Messages.LoadBalancerAccumulatedStatsRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getGetClientAccumulatedStatsMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service LoadBalancerStatsService. + *
+   * A service used to obtain stats for verifying LB behavior.
+   * 
+ */ public static final class LoadBalancerStatsServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private LoadBalancerStatsServiceBlockingStub( diff --git a/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/MetricsServiceGrpc.java b/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/MetricsServiceGrpc.java index 1650365bd52..3104f7b263e 100644 --- a/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/MetricsServiceGrpc.java +++ b/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/MetricsServiceGrpc.java @@ -91,6 +91,21 @@ public MetricsServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions c return MetricsServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static MetricsServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public MetricsServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new MetricsServiceBlockingV2Stub(channel, callOptions); + } + }; + return MetricsServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -201,6 +216,46 @@ public void getGauge(io.grpc.testing.integration.Metrics.GaugeRequest request, /** * A stub to allow clients to do synchronous rpc calls to service MetricsService. */ + public static final class MetricsServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private MetricsServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected MetricsServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new MetricsServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * Returns the values of all the gauges that are currently being maintained by
+     * the service
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + getAllGauges(io.grpc.testing.integration.Metrics.EmptyMessage request) { + return io.grpc.stub.ClientCalls.blockingV2ServerStreamingCall( + getChannel(), getGetAllGaugesMethod(), getCallOptions(), request); + } + + /** + *
+     * Returns the value of one gauge
+     * 
+ */ + public io.grpc.testing.integration.Metrics.GaugeResponse getGauge(io.grpc.testing.integration.Metrics.GaugeRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getGetGaugeMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service MetricsService. + */ public static final class MetricsServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private MetricsServiceBlockingStub( diff --git a/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/ReconnectServiceGrpc.java b/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/ReconnectServiceGrpc.java index d1887ee83c4..39df95f4d90 100644 --- a/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/ReconnectServiceGrpc.java +++ b/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/ReconnectServiceGrpc.java @@ -94,6 +94,21 @@ public ReconnectServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions return ReconnectServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static ReconnectServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public ReconnectServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new ReconnectServiceBlockingV2Stub(channel, callOptions); + } + }; + return ReconnectServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -202,6 +217,40 @@ public void stop(io.grpc.testing.integration.EmptyProtos.Empty request, * A service used to control reconnect server. * */ + public static final class ReconnectServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private ReconnectServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected ReconnectServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new ReconnectServiceBlockingV2Stub(channel, callOptions); + } + + /** + */ + public io.grpc.testing.integration.EmptyProtos.Empty start(io.grpc.testing.integration.Messages.ReconnectParams request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getStartMethod(), getCallOptions(), request); + } + + /** + */ + public io.grpc.testing.integration.Messages.ReconnectInfo stop(io.grpc.testing.integration.EmptyProtos.Empty request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getStopMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service ReconnectService. + *
+   * A service used to control reconnect server.
+   * 
+ */ public static final class ReconnectServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private ReconnectServiceBlockingStub( diff --git a/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/TestServiceGrpc.java b/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/TestServiceGrpc.java index 08071a3b653..2b519686d85 100644 --- a/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/TestServiceGrpc.java +++ b/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/TestServiceGrpc.java @@ -281,6 +281,21 @@ public TestServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions call return TestServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static TestServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public TestServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new TestServiceBlockingV2Stub(channel, callOptions); + } + }; + return TestServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -551,6 +566,125 @@ public void unimplementedCall(io.grpc.testing.integration.EmptyProtos.Empty requ * performance with various types of payload. * */ + public static final class TestServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private TestServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected TestServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new TestServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * One empty request followed by one empty response.
+     * 
+ */ + public io.grpc.testing.integration.EmptyProtos.Empty emptyCall(io.grpc.testing.integration.EmptyProtos.Empty request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getEmptyCallMethod(), getCallOptions(), request); + } + + /** + *
+     * One request followed by one response.
+     * 
+ */ + public io.grpc.testing.integration.Messages.SimpleResponse unaryCall(io.grpc.testing.integration.Messages.SimpleRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getUnaryCallMethod(), getCallOptions(), request); + } + + /** + *
+     * One request followed by one response. Response has cache control
+     * headers set such that a caching HTTP proxy (such as GFE) can
+     * satisfy subsequent requests.
+     * 
+ */ + public io.grpc.testing.integration.Messages.SimpleResponse cacheableUnaryCall(io.grpc.testing.integration.Messages.SimpleRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getCacheableUnaryCallMethod(), getCallOptions(), request); + } + + /** + *
+     * One request followed by a sequence of responses (streamed download).
+     * The server returns the payload with client desired type and sizes.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + streamingOutputCall(io.grpc.testing.integration.Messages.StreamingOutputCallRequest request) { + return io.grpc.stub.ClientCalls.blockingV2ServerStreamingCall( + getChannel(), getStreamingOutputCallMethod(), getCallOptions(), request); + } + + /** + *
+     * A sequence of requests followed by one response (streamed upload).
+     * The server returns the aggregated size of client payload as the result.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + streamingInputCall() { + return io.grpc.stub.ClientCalls.blockingClientStreamingCall( + getChannel(), getStreamingInputCallMethod(), getCallOptions()); + } + + /** + *
+     * A sequence of requests with each request served by the server immediately.
+     * As one request could lead to multiple responses, this interface
+     * demonstrates the idea of full duplexing.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + fullDuplexCall() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getFullDuplexCallMethod(), getCallOptions()); + } + + /** + *
+     * A sequence of requests followed by a sequence of responses.
+     * The server buffers all the client requests and then serves them in order. A
+     * stream of responses are returned to the client when the server starts with
+     * first request.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + halfDuplexCall() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getHalfDuplexCallMethod(), getCallOptions()); + } + + /** + *
+     * The test server will not implement this method. It will be used
+     * to test the behavior when clients call unimplemented methods.
+     * 
+ */ + public io.grpc.testing.integration.EmptyProtos.Empty unimplementedCall(io.grpc.testing.integration.EmptyProtos.Empty request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getUnimplementedCallMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service TestService. + *
+   * A simple service to test the various types of RPCs and experiment with
+   * performance with various types of payload.
+   * 
+ */ public static final class TestServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private TestServiceBlockingStub( diff --git a/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/UnimplementedServiceGrpc.java b/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/UnimplementedServiceGrpc.java index 9711386185e..400ac6dc4a3 100644 --- a/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/UnimplementedServiceGrpc.java +++ b/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/UnimplementedServiceGrpc.java @@ -64,6 +64,21 @@ public UnimplementedServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOpt return UnimplementedServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static UnimplementedServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public UnimplementedServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new UnimplementedServiceBlockingV2Stub(channel, callOptions); + } + }; + return UnimplementedServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -167,6 +182,37 @@ public void unimplementedCall(io.grpc.testing.integration.EmptyProtos.Empty requ * that case. * */ + public static final class UnimplementedServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private UnimplementedServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected UnimplementedServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new UnimplementedServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * A call that no server should implement
+     * 
+ */ + public io.grpc.testing.integration.EmptyProtos.Empty unimplementedCall(io.grpc.testing.integration.EmptyProtos.Empty request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getUnimplementedCallMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service UnimplementedService. + *
+   * A simple service NOT implemented at servers so clients can test for
+   * that case.
+   * 
+ */ public static final class UnimplementedServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private UnimplementedServiceBlockingStub( diff --git a/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/XdsUpdateClientConfigureServiceGrpc.java b/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/XdsUpdateClientConfigureServiceGrpc.java index 164119a29e7..9cc13780723 100644 --- a/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/XdsUpdateClientConfigureServiceGrpc.java +++ b/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/XdsUpdateClientConfigureServiceGrpc.java @@ -63,6 +63,21 @@ public XdsUpdateClientConfigureServiceStub newStub(io.grpc.Channel channel, io.g return XdsUpdateClientConfigureServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static XdsUpdateClientConfigureServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public XdsUpdateClientConfigureServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new XdsUpdateClientConfigureServiceBlockingV2Stub(channel, callOptions); + } + }; + return XdsUpdateClientConfigureServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -162,6 +177,36 @@ public void configure(io.grpc.testing.integration.Messages.ClientConfigureReques * A service to dynamically update the configuration of an xDS test client. * */ + public static final class XdsUpdateClientConfigureServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private XdsUpdateClientConfigureServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected XdsUpdateClientConfigureServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new XdsUpdateClientConfigureServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * Update the tes client's configuration.
+     * 
+ */ + public io.grpc.testing.integration.Messages.ClientConfigureResponse configure(io.grpc.testing.integration.Messages.ClientConfigureRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getConfigureMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service XdsUpdateClientConfigureService. + *
+   * A service to dynamically update the configuration of an xDS test client.
+   * 
+ */ public static final class XdsUpdateClientConfigureServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private XdsUpdateClientConfigureServiceBlockingStub( diff --git a/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/XdsUpdateHealthServiceGrpc.java b/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/XdsUpdateHealthServiceGrpc.java index dccd23ccbee..8243ba713fa 100644 --- a/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/XdsUpdateHealthServiceGrpc.java +++ b/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/XdsUpdateHealthServiceGrpc.java @@ -94,6 +94,21 @@ public XdsUpdateHealthServiceStub newStub(io.grpc.Channel channel, io.grpc.CallO return XdsUpdateHealthServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static XdsUpdateHealthServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public XdsUpdateHealthServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new XdsUpdateHealthServiceBlockingV2Stub(channel, callOptions); + } + }; + return XdsUpdateHealthServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -202,6 +217,40 @@ public void setNotServing(io.grpc.testing.integration.EmptyProtos.Empty request, * A service to remotely control health status of an xDS test server. * */ + public static final class XdsUpdateHealthServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private XdsUpdateHealthServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected XdsUpdateHealthServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new XdsUpdateHealthServiceBlockingV2Stub(channel, callOptions); + } + + /** + */ + public io.grpc.testing.integration.EmptyProtos.Empty setServing(io.grpc.testing.integration.EmptyProtos.Empty request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getSetServingMethod(), getCallOptions(), request); + } + + /** + */ + public io.grpc.testing.integration.EmptyProtos.Empty setNotServing(io.grpc.testing.integration.EmptyProtos.Empty request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getSetNotServingMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service XdsUpdateHealthService. + *
+   * A service to remotely control health status of an xDS test server.
+   * 
+ */ public static final class XdsUpdateHealthServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private XdsUpdateHealthServiceBlockingStub( diff --git a/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceImpl.java b/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceImpl.java index 8fa272122d0..a9ee9382495 100644 --- a/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceImpl.java +++ b/interop-testing/src/main/java/io/grpc/testing/integration/TestServiceImpl.java @@ -18,6 +18,7 @@ import com.google.common.base.Preconditions; import com.google.common.collect.Queues; +import com.google.errorprone.annotations.concurrent.GuardedBy; import com.google.protobuf.ByteString; import io.grpc.ForwardingServerCall.SimpleForwardingServerCall; import io.grpc.Metadata; @@ -54,7 +55,6 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; -import javax.annotation.concurrent.GuardedBy; /** * Implementation of the business logic for the TestService. Uses an executor to schedule chunks diff --git a/interop-testing/src/main/java/io/grpc/testing/integration/XdsTestClient.java b/interop-testing/src/main/java/io/grpc/testing/integration/XdsTestClient.java index 23bc12a6b65..89519041a79 100644 --- a/interop-testing/src/main/java/io/grpc/testing/integration/XdsTestClient.java +++ b/interop-testing/src/main/java/io/grpc/testing/integration/XdsTestClient.java @@ -78,6 +78,7 @@ import java.util.logging.Logger; import javax.annotation.Nullable; import javax.annotation.concurrent.ThreadSafe; +import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement; /** Client for xDS interop tests. */ public final class XdsTestClient { @@ -261,6 +262,7 @@ private static RpcType parseRpc(String rpc) { } } + @IgnoreJRERequirement // OpenTelemetry uses Java 8+ APIs private void run() { if (enableCsmObservability) { csmObservability = CsmObservability.newBuilder() diff --git a/interop-testing/src/main/java/io/grpc/testing/integration/XdsTestServer.java b/interop-testing/src/main/java/io/grpc/testing/integration/XdsTestServer.java index 1bc4ff88981..88f1bf468b6 100644 --- a/interop-testing/src/main/java/io/grpc/testing/integration/XdsTestServer.java +++ b/interop-testing/src/main/java/io/grpc/testing/integration/XdsTestServer.java @@ -57,6 +57,7 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; +import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement; /** Interop test server that implements the xDS testing service. */ public final class XdsTestServer { @@ -193,6 +194,7 @@ void parseArgs(String[] args) { } @SuppressWarnings("AddressSelection") + @IgnoreJRERequirement // OpenTelemetry uses Java 8+ APIs void start() throws Exception { if (enableCsmObservability) { csmObservability = CsmObservability.newBuilder() diff --git a/istio-interop-testing/build.gradle b/istio-interop-testing/build.gradle index e2fe228f13b..4550f0ea202 100644 --- a/istio-interop-testing/build.gradle +++ b/istio-interop-testing/build.gradle @@ -28,7 +28,11 @@ dependencies { libraries.junit, libraries.truth - signature libraries.signature.java + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } } sourceSets { diff --git a/istio-interop-testing/src/generated/main/grpc/io/istio/test/EchoTestServiceGrpc.java b/istio-interop-testing/src/generated/main/grpc/io/istio/test/EchoTestServiceGrpc.java index 1f48c16aed3..3cb27ac1067 100644 --- a/istio-interop-testing/src/generated/main/grpc/io/istio/test/EchoTestServiceGrpc.java +++ b/istio-interop-testing/src/generated/main/grpc/io/istio/test/EchoTestServiceGrpc.java @@ -91,6 +91,21 @@ public EchoTestServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions return EchoTestServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static EchoTestServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public EchoTestServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new EchoTestServiceBlockingV2Stub(channel, callOptions); + } + }; + return EchoTestServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -187,6 +202,37 @@ public void forwardEcho(io.istio.test.Echo.ForwardEchoRequest request, /** * A stub to allow clients to do synchronous rpc calls to service EchoTestService. */ + public static final class EchoTestServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private EchoTestServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected EchoTestServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new EchoTestServiceBlockingV2Stub(channel, callOptions); + } + + /** + */ + public io.istio.test.Echo.EchoResponse echo(io.istio.test.Echo.EchoRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getEchoMethod(), getCallOptions(), request); + } + + /** + */ + public io.istio.test.Echo.ForwardEchoResponse forwardEcho(io.istio.test.Echo.ForwardEchoRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getForwardEchoMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service EchoTestService. + */ public static final class EchoTestServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private EchoTestServiceBlockingStub( diff --git a/netty/BUILD.bazel b/netty/BUILD.bazel index 9fe52ea5868..52fdcb19fd8 100644 --- a/netty/BUILD.bazel +++ b/netty/BUILD.bazel @@ -27,6 +27,7 @@ java_library( artifact("io.netty:netty-transport"), artifact("io.netty:netty-transport-native-unix-common"), artifact("io.perfmark:perfmark-api"), + artifact("org.codehaus.mojo:animal-sniffer-annotations"), ], ) diff --git a/netty/build.gradle b/netty/build.gradle index 5533038c85b..cb97ae10b55 100644 --- a/netty/build.gradle +++ b/netty/build.gradle @@ -17,6 +17,7 @@ tasks.named("jar").configure { dependencies { api project(':grpc-api'), + libraries.animalsniffer.annotations, libraries.netty.codec.http2 implementation project(':grpc-core'), libs.netty.handler.proxy, @@ -65,8 +66,16 @@ dependencies { classifier = "linux-x86_64" } } - signature libraries.signature.java - signature libraries.signature.android + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } + signature (libraries.signature.android) { + artifact { + extension = "signature" + } + } } import net.ltgt.gradle.errorprone.CheckSeverity diff --git a/netty/shaded/build.gradle b/netty/shaded/build.gradle index 25682d60b75..f805a4f4a1f 100644 --- a/netty/shaded/build.gradle +++ b/netty/shaded/build.gradle @@ -65,8 +65,16 @@ dependencies { shadow project(':grpc-netty').configurations.runtimeClasspath.allDependencies.matching { it.group != 'io.netty' } - signature libraries.signature.java - signature libraries.signature.android + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } + signature (libraries.signature.android) { + artifact { + extension = "signature" + } + } } tasks.named("jar").configure { diff --git a/netty/src/main/java/io/grpc/netty/CancelServerStreamCommand.java b/netty/src/main/java/io/grpc/netty/CancelServerStreamCommand.java index d49e3bd672b..a3b29457670 100644 --- a/netty/src/main/java/io/grpc/netty/CancelServerStreamCommand.java +++ b/netty/src/main/java/io/grpc/netty/CancelServerStreamCommand.java @@ -69,13 +69,14 @@ public boolean equals(Object o) { CancelServerStreamCommand that = (CancelServerStreamCommand) o; - return Objects.equal(this.stream, that.stream) - && Objects.equal(this.reason, that.reason); + return this.stream.equals(that.stream) + && this.reason.equals(that.reason) + && this.peerNotify.equals(that.peerNotify); } @Override public int hashCode() { - return Objects.hashCode(stream, reason); + return Objects.hashCode(stream, reason, peerNotify); } @Override @@ -83,6 +84,7 @@ public String toString() { return MoreObjects.toStringHelper(this) .add("stream", stream) .add("reason", reason) + .add("peerNotify", peerNotify) .toString(); } diff --git a/netty/src/main/java/io/grpc/netty/InternalProtocolNegotiators.java b/netty/src/main/java/io/grpc/netty/InternalProtocolNegotiators.java index 8aeb44d0fc2..3d1aa83d9ff 100644 --- a/netty/src/main/java/io/grpc/netty/InternalProtocolNegotiators.java +++ b/netty/src/main/java/io/grpc/netty/InternalProtocolNegotiators.java @@ -16,6 +16,7 @@ package io.grpc.netty; +import com.google.common.base.Optional; import io.grpc.ChannelLogger; import io.grpc.internal.ObjectPool; import io.grpc.netty.ProtocolNegotiators.ClientTlsHandler; @@ -24,7 +25,6 @@ import io.netty.channel.ChannelHandler; import io.netty.handler.ssl.SslContext; import io.netty.util.AsciiString; -import java.util.Optional; import java.util.concurrent.Executor; /** @@ -72,7 +72,7 @@ public void close() { * may happen immediately, even before the TLS Handshake is complete. */ public static InternalProtocolNegotiator.ProtocolNegotiator tls(SslContext sslContext) { - return tls(sslContext, null, Optional.empty()); + return tls(sslContext, null, Optional.absent()); } /** @@ -170,7 +170,7 @@ public static ChannelHandler clientTlsHandler( ChannelHandler next, SslContext sslContext, String authority, ChannelLogger negotiationLogger) { return new ClientTlsHandler(next, sslContext, authority, null, negotiationLogger, - Optional.empty()); + Optional.absent()); } public static class ProtocolNegotiationHandler diff --git a/netty/src/main/java/io/grpc/netty/NettyChannelBuilder.java b/netty/src/main/java/io/grpc/netty/NettyChannelBuilder.java index fe226ec2ba9..8b80f7b4e46 100644 --- a/netty/src/main/java/io/grpc/netty/NettyChannelBuilder.java +++ b/netty/src/main/java/io/grpc/netty/NettyChannelBuilder.java @@ -23,6 +23,7 @@ import static io.grpc.internal.GrpcUtil.KEEPALIVE_TIME_NANOS_DISABLED; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Optional; import com.google.common.base.Ticker; import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.CheckReturnValue; @@ -63,7 +64,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; -import java.util.Optional; import java.util.concurrent.Executor; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -652,7 +652,7 @@ static ProtocolNegotiator createProtocolNegotiatorByType( case PLAINTEXT_UPGRADE: return ProtocolNegotiators.plaintextUpgrade(); case TLS: - return ProtocolNegotiators.tls(sslContext, executorPool, Optional.empty()); + return ProtocolNegotiators.tls(sslContext, executorPool, Optional.absent()); default: throw new IllegalArgumentException("Unsupported negotiationType: " + negotiationType); } diff --git a/netty/src/main/java/io/grpc/netty/ProtocolNegotiationEvent.java b/netty/src/main/java/io/grpc/netty/ProtocolNegotiationEvent.java index 16da79e1af8..8103a2dc79f 100644 --- a/netty/src/main/java/io/grpc/netty/ProtocolNegotiationEvent.java +++ b/netty/src/main/java/io/grpc/netty/ProtocolNegotiationEvent.java @@ -20,10 +20,10 @@ import com.google.common.base.MoreObjects; import com.google.common.base.Objects; +import com.google.errorprone.annotations.CheckReturnValue; import io.grpc.Attributes; import io.grpc.Internal; import io.grpc.InternalChannelz.Security; -import javax.annotation.CheckReturnValue; import javax.annotation.Nullable; /** diff --git a/netty/src/main/java/io/grpc/netty/ProtocolNegotiators.java b/netty/src/main/java/io/grpc/netty/ProtocolNegotiators.java index 84370ac8153..3f4d59bb334 100644 --- a/netty/src/main/java/io/grpc/netty/ProtocolNegotiators.java +++ b/netty/src/main/java/io/grpc/netty/ProtocolNegotiators.java @@ -20,6 +20,7 @@ import static com.google.common.base.Preconditions.checkState; import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.errorprone.annotations.ForOverride; import io.grpc.Attributes; @@ -72,7 +73,6 @@ import java.nio.channels.ClosedChannelException; import java.util.Arrays; import java.util.EnumSet; -import java.util.Optional; import java.util.Set; import java.util.concurrent.Executor; import java.util.logging.Level; @@ -82,6 +82,7 @@ import javax.net.ssl.SSLException; import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLSession; +import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement; /** * Common {@link ProtocolNegotiator}s used by gRPC. @@ -601,6 +602,7 @@ static final class ClientTlsHandler extends ProtocolNegotiationHandler { } @Override + @IgnoreJRERequirement protected void handlerAdded0(ChannelHandlerContext ctx) { SSLEngine sslEngine = sslContext.newEngine(ctx.alloc(), host, port); SSLParameters sslParams = sslEngine.getSSLParameters(); @@ -708,7 +710,7 @@ public static ProtocolNegotiator tls(SslContext sslContext, * may happen immediately, even before the TLS Handshake is complete. */ public static ProtocolNegotiator tls(SslContext sslContext) { - return tls(sslContext, null, Optional.empty()); + return tls(sslContext, null, Optional.absent()); } public static ProtocolNegotiator.ClientFactory tlsClientFactory(SslContext sslContext) { diff --git a/netty/src/main/java/io/grpc/netty/Utils.java b/netty/src/main/java/io/grpc/netty/Utils.java index ba405637af5..c0981f5b219 100644 --- a/netty/src/main/java/io/grpc/netty/Utils.java +++ b/netty/src/main/java/io/grpc/netty/Utils.java @@ -27,6 +27,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; +import com.google.errorprone.annotations.CheckReturnValue; import io.grpc.InternalChannelz; import io.grpc.InternalMetadata; import io.grpc.Metadata; @@ -68,7 +69,6 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; -import javax.annotation.CheckReturnValue; import javax.annotation.Nullable; import javax.net.ssl.SSLException; diff --git a/netty/src/main/java/io/grpc/netty/package-info.java b/netty/src/main/java/io/grpc/netty/package-info.java index 54595b38573..d1d7b87cf51 100644 --- a/netty/src/main/java/io/grpc/netty/package-info.java +++ b/netty/src/main/java/io/grpc/netty/package-info.java @@ -18,5 +18,5 @@ * The main transport implementation based on Netty, * for both the client and the server. */ -@javax.annotation.CheckReturnValue +@com.google.errorprone.annotations.CheckReturnValue package io.grpc.netty; diff --git a/netty/src/test/java/io/grpc/netty/NettyAdaptiveCumulatorTest.java b/netty/src/test/java/io/grpc/netty/NettyAdaptiveCumulatorTest.java index 1037dab4712..68dc6dc0c80 100644 --- a/netty/src/test/java/io/grpc/netty/NettyAdaptiveCumulatorTest.java +++ b/netty/src/test/java/io/grpc/netty/NettyAdaptiveCumulatorTest.java @@ -40,7 +40,6 @@ import io.netty.buffer.UnpooledByteBufAllocator; import java.util.Collection; import java.util.List; -import java.util.stream.Collectors; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -55,7 +54,7 @@ public class NettyAdaptiveCumulatorTest { private static Collection cartesianProductParams(List... lists) { - return Lists.cartesianProduct(lists).stream().map(List::toArray).collect(Collectors.toList()); + return Lists.transform(Lists.cartesianProduct(lists), List::toArray); } @RunWith(JUnit4.class) diff --git a/netty/src/test/java/io/grpc/netty/NettyClientStreamTest.java b/netty/src/test/java/io/grpc/netty/NettyClientStreamTest.java index 2a5a0df279a..a44a196ac8c 100644 --- a/netty/src/test/java/io/grpc/netty/NettyClientStreamTest.java +++ b/netty/src/test/java/io/grpc/netty/NettyClientStreamTest.java @@ -46,6 +46,7 @@ import static org.mockito.Mockito.when; import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.Iterables; import com.google.common.io.BaseEncoding; import io.grpc.CallOptions; import io.grpc.InternalStatus; @@ -239,11 +240,13 @@ public void writeFrameFutureFailedShouldCancelRpc() { // Get the CancelClientStreamCommand written to the queue. Above we verified that there is // only one CancelClientStreamCommand enqueued, and is the third enqueued command (create, // frame write failure, cancel). - CancelClientStreamCommand cancelCommand = Mockito.mockingDetails(writeQueue).getInvocations() - // Get enqueue() innovations only - .stream().filter(invocation -> invocation.getMethod().getName().equals("enqueue")) + CancelClientStreamCommand cancelCommand = Iterables.get( + Iterables.filter( + Mockito.mockingDetails(writeQueue).getInvocations(), + // Get enqueue() innovations only + invocation -> invocation.getMethod().getName().equals("enqueue")), // Get the third invocation of enqueue() - .skip(2).findFirst().get() + 2) // Get the first argument (QueuedCommand command) .getArgument(0); diff --git a/netty/src/test/java/io/grpc/netty/NettyClientTransportTest.java b/netty/src/test/java/io/grpc/netty/NettyClientTransportTest.java index b7a3ff13a59..d0a6456c430 100644 --- a/netty/src/test/java/io/grpc/netty/NettyClientTransportTest.java +++ b/netty/src/test/java/io/grpc/netty/NettyClientTransportTest.java @@ -37,8 +37,11 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import com.google.common.base.Optional; import com.google.common.base.Strings; import com.google.common.base.Ticker; import com.google.common.io.ByteStreams; @@ -94,6 +97,7 @@ import io.netty.handler.ssl.ClientAuth; import io.netty.handler.ssl.SslContext; import io.netty.util.AsciiString; +import io.netty.util.ReferenceCountUtil; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -105,7 +109,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -187,6 +190,7 @@ public void addDefaultUserAgent() throws Exception { startServer(); NettyClientTransport transport = newTransport(newNegotiator()); callMeMaybe(transport.start(clientTransportListener)); + verify(clientTransportListener, timeout(5000)).transportReady(); // Send a single RPC and wait for the response. new Rpc(transport).halfClose().waitForResponse(); @@ -244,6 +248,7 @@ public void overrideDefaultUserAgent() throws Exception { NettyClientTransport transport = newTransport(newNegotiator(), DEFAULT_MAX_MESSAGE_SIZE, GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE, "testUserAgent", true); callMeMaybe(transport.start(clientTransportListener)); + verify(clientTransportListener, timeout(5000)).transportReady(); new Rpc(transport, new Metadata()).halfClose().waitForResponse(); @@ -261,6 +266,7 @@ public void maxMessageSizeShouldBeEnforced() throws Throwable { NettyClientTransport transport = newTransport(newNegotiator(), 1, GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE, null, true); callMeMaybe(transport.start(clientTransportListener)); + verify(clientTransportListener, timeout(5000)).transportReady(); try { // Send a single RPC and wait for the response. @@ -287,6 +293,7 @@ public void creatingMultipleTlsTransportsShouldSucceed() throws Exception { NettyClientTransport transport = newTransport(negotiator); callMeMaybe(transport.start(clientTransportListener)); } + verify(clientTransportListener, timeout(5000).times(2)).transportReady(); // Send a single RPC on each transport. final List rpcs = new ArrayList<>(transports.size()); @@ -316,6 +323,7 @@ public void run() { failureStatus.asRuntimeException()); } }); + verify(clientTransportListener, timeout(5000)).transportTerminated(); Rpc rpc = new Rpc(transport).halfClose(); try { @@ -349,6 +357,7 @@ public void tlsNegotiationFailurePropagatesToStatus() throws Exception { ProtocolNegotiator negotiator = ProtocolNegotiators.tls(clientContext); final NettyClientTransport transport = newTransport(negotiator); callMeMaybe(transport.start(clientTransportListener)); + verify(clientTransportListener, timeout(5000)).transportTerminated(); Rpc rpc = new Rpc(transport).halfClose(); try { @@ -378,6 +387,7 @@ public void channelExceptionDuringNegotiatonPropagatesToStatus() throws Exceptio callMeMaybe(transport.start(clientTransportListener)); final Status failureStatus = Status.UNAVAILABLE.withDescription("oh noes!"); transport.channel().pipeline().fireExceptionCaught(failureStatus.asRuntimeException()); + verify(clientTransportListener, timeout(5000)).transportTerminated(); Rpc rpc = new Rpc(transport).halfClose(); try { @@ -409,6 +419,7 @@ public void run() { } } }); + verify(clientTransportListener, timeout(5000)).transportTerminated(); Rpc rpc = new Rpc(transport).halfClose(); try { @@ -428,6 +439,7 @@ public void bufferedStreamsShouldBeClosedWhenConnectionTerminates() throws Excep NettyClientTransport transport = newTransport(newNegotiator()); callMeMaybe(transport.start(clientTransportListener)); + verify(clientTransportListener, timeout(5000)).transportReady(); // Send a dummy RPC in order to ensure that the updated SETTINGS_MAX_CONCURRENT_STREAMS // has been received by the remote endpoint. @@ -579,6 +591,7 @@ public void maxHeaderListSizeShouldBeEnforcedOnClient() throws Exception { NettyClientTransport transport = newTransport(newNegotiator(), DEFAULT_MAX_MESSAGE_SIZE, 1, null, true); callMeMaybe(transport.start(clientTransportListener)); + verify(clientTransportListener, timeout(5000)).transportReady(); try { // Send a single RPC and wait for the response. @@ -612,6 +625,7 @@ public void huffmanCodingShouldNotBePerformed() throws Exception { longStringOfA); callMeMaybe(transport.start(clientTransportListener)); + verify(clientTransportListener, timeout(5000)).transportReady(); AtomicBoolean foundExpectedHeaderBytes = new AtomicBoolean(false); @@ -641,6 +655,7 @@ public void maxHeaderListSizeShouldBeEnforcedOnServer() throws Exception { NettyClientTransport transport = newTransport(newNegotiator()); callMeMaybe(transport.start(clientTransportListener)); + verify(clientTransportListener, timeout(5000)).transportReady(); try { // Send a single RPC and wait for the response. @@ -685,6 +700,7 @@ public void clientStreamGetsAttributes() throws Exception { startServer(); NettyClientTransport transport = newTransport(newNegotiator()); callMeMaybe(transport.start(clientTransportListener)); + verify(clientTransportListener, timeout(5000)).transportReady(); Rpc rpc = new Rpc(transport).halfClose(); rpc.waitForResponse(); @@ -703,6 +719,7 @@ public void keepAliveEnabled() throws Exception { NettyClientTransport transport = newTransport(newNegotiator(), DEFAULT_MAX_MESSAGE_SIZE, GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE, null /* user agent */, true /* keep alive */); callMeMaybe(transport.start(clientTransportListener)); + verify(clientTransportListener, timeout(5000)).transportReady(); Rpc rpc = new Rpc(transport).halfClose(); rpc.waitForResponse(); @@ -715,6 +732,7 @@ public void keepAliveDisabled() throws Exception { NettyClientTransport transport = newTransport(newNegotiator(), DEFAULT_MAX_MESSAGE_SIZE, GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE, null /* user agent */, false /* keep alive */); callMeMaybe(transport.start(clientTransportListener)); + verify(clientTransportListener, timeout(5000)).transportReady(); Rpc rpc = new Rpc(transport).halfClose(); rpc.waitForResponse(); @@ -803,11 +821,12 @@ public void tlsNegotiationServerExecutorShouldSucceed() throws Exception { .keyManager(clientCert, clientKey) .build(); ProtocolNegotiator negotiator = ProtocolNegotiators.tls(clientContext, clientExecutorPool, - Optional.empty()); + Optional.absent()); // after starting the client, the Executor in the client pool should be used assertEquals(true, clientExecutorPool.isInUse()); final NettyClientTransport transport = newTransport(negotiator); callMeMaybe(transport.start(clientTransportListener)); + verify(clientTransportListener, timeout(5000)).transportReady(); Rpc rpc = new Rpc(transport).halfClose(); rpc.waitForResponse(); // closing the negotiators should return the executors back to pool, and release the resource @@ -1098,9 +1117,15 @@ public NoopHandler(GrpcHttp2ConnectionHandler grpcHandler) { this.grpcHandler = grpcHandler; } + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) { + // Prevent any data being passed to NettyClientHandler + ReferenceCountUtil.release(msg); + } + @Override public void channelRegistered(ChannelHandlerContext ctx) throws Exception { - ctx.pipeline().addBefore(ctx.name(), null, grpcHandler); + ctx.pipeline().addAfter(ctx.name(), null, grpcHandler); } public void fail(ChannelHandlerContext ctx, Throwable cause) { diff --git a/netty/src/test/java/io/grpc/netty/NettyServerStreamTest.java b/netty/src/test/java/io/grpc/netty/NettyServerStreamTest.java index 452f68341b1..0723e359752 100644 --- a/netty/src/test/java/io/grpc/netty/NettyServerStreamTest.java +++ b/netty/src/test/java/io/grpc/netty/NettyServerStreamTest.java @@ -38,7 +38,9 @@ import com.google.common.base.Strings; import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.Iterables; import com.google.common.collect.ListMultimap; +import com.google.common.collect.Lists; import io.grpc.Attributes; import io.grpc.Metadata; import io.grpc.Status; @@ -57,7 +59,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Queue; -import java.util.stream.Collectors; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -217,14 +218,15 @@ private CancelServerStreamCommand findCancelServerStreamCommand() { // Ensure there's no CancelServerStreamCommand enqueued with flush=false. verify(writeQueue, never()).enqueue(any(CancelServerStreamCommand.class), eq(false)); - List commands = Mockito.mockingDetails(writeQueue).getInvocations() - .stream() - // Get enqueue() innovations only. - .filter(invocation -> invocation.getMethod().getName().equals("enqueue")) - // Find the cancel commands. - .filter(invocation -> invocation.getArgument(0) instanceof CancelServerStreamCommand) - .map(invocation -> invocation.getArgument(0, CancelServerStreamCommand.class)) - .collect(Collectors.toList()); + List commands = Lists.newArrayList( + Iterables.transform( + Iterables.filter( + Mockito.mockingDetails(writeQueue).getInvocations(), + // Get enqueue() innovations only + invocation -> invocation.getMethod().getName().equals("enqueue") + // Find the cancel commands. + && invocation.getArgument(0) instanceof CancelServerStreamCommand), + invocation -> invocation.getArgument(0, CancelServerStreamCommand.class))); assertWithMessage("Expected exactly one CancelClientStreamCommand").that(commands).hasSize(1); return commands.get(0); diff --git a/netty/src/test/java/io/grpc/netty/ProtocolNegotiatorsTest.java b/netty/src/test/java/io/grpc/netty/ProtocolNegotiatorsTest.java index 2ccdb2de543..6dff3de2b2a 100644 --- a/netty/src/test/java/io/grpc/netty/ProtocolNegotiatorsTest.java +++ b/netty/src/test/java/io/grpc/netty/ProtocolNegotiatorsTest.java @@ -31,6 +31,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import com.google.common.base.Optional; import io.grpc.Attributes; import io.grpc.CallCredentials; import io.grpc.ChannelCredentials; @@ -120,7 +121,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.Optional; import java.util.Queue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -877,7 +877,7 @@ public String applicationProtocol() { DefaultEventLoopGroup elg = new DefaultEventLoopGroup(1); ClientTlsHandler handler = new ClientTlsHandler(grpcHandler, sslContext, - "authority", elg, noopLogger, Optional.empty()); + "authority", elg, noopLogger, Optional.absent()); pipeline.addLast(handler); pipeline.replace(SslHandler.class, null, goodSslHandler); pipeline.fireUserEventTriggered(ProtocolNegotiationEvent.DEFAULT); @@ -915,7 +915,7 @@ public String applicationProtocol() { .applicationProtocolConfig(apn).build(); ClientTlsHandler handler = new ClientTlsHandler(grpcHandler, sslContext, - "authority", elg, noopLogger, Optional.empty()); + "authority", elg, noopLogger, Optional.absent()); pipeline.addLast(handler); pipeline.replace(SslHandler.class, null, goodSslHandler); pipeline.fireUserEventTriggered(ProtocolNegotiationEvent.DEFAULT); @@ -939,7 +939,7 @@ public String applicationProtocol() { DefaultEventLoopGroup elg = new DefaultEventLoopGroup(1); ClientTlsHandler handler = new ClientTlsHandler(grpcHandler, sslContext, - "authority", elg, noopLogger, Optional.empty()); + "authority", elg, noopLogger, Optional.absent()); pipeline.addLast(handler); final AtomicReference error = new AtomicReference<>(); @@ -967,7 +967,7 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { @Test public void clientTlsHandler_closeDuringNegotiation() throws Exception { ClientTlsHandler handler = new ClientTlsHandler(grpcHandler, sslContext, - "authority", null, noopLogger, Optional.empty()); + "authority", null, noopLogger, Optional.absent()); pipeline.addLast(new WriteBufferingAndExceptionHandler(handler)); ChannelFuture pendingWrite = channel.writeAndFlush(NettyClientHandler.NOOP_MESSAGE); @@ -1230,7 +1230,7 @@ public void clientTlsHandler_firesNegotiation() throws Exception { } FakeGrpcHttp2ConnectionHandler gh = FakeGrpcHttp2ConnectionHandler.newHandler(); ClientTlsProtocolNegotiator pn = new ClientTlsProtocolNegotiator(clientSslContext, - null, Optional.empty()); + null, Optional.absent()); WriteBufferingAndExceptionHandler clientWbaeh = new WriteBufferingAndExceptionHandler(pn.newHandler(gh)); diff --git a/okhttp/build.gradle b/okhttp/build.gradle index 063e4775de1..6c542feec9c 100644 --- a/okhttp/build.gradle +++ b/okhttp/build.gradle @@ -31,8 +31,16 @@ dependencies { project(':grpc-testing-proto'), libraries.netty.codec.http2, libraries.okhttp - signature libraries.signature.java - signature libraries.signature.android + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } + signature (libraries.signature.android) { + artifact { + extension = "signature" + } + } } project.sourceSets { diff --git a/okhttp/src/main/java/io/grpc/okhttp/AsyncSink.java b/okhttp/src/main/java/io/grpc/okhttp/AsyncSink.java index 1ac64d7ebb5..01ee23b905c 100644 --- a/okhttp/src/main/java/io/grpc/okhttp/AsyncSink.java +++ b/okhttp/src/main/java/io/grpc/okhttp/AsyncSink.java @@ -19,6 +19,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.internal.SerializingExecutor; import io.grpc.okhttp.ExceptionHandlingFrameWriter.TransportExceptionHandler; import io.grpc.okhttp.internal.framed.ErrorCode; @@ -30,7 +31,6 @@ import java.io.IOException; import java.net.Socket; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; import okio.Buffer; import okio.Sink; import okio.Timeout; diff --git a/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java index dcffd7daad1..657c5cc1793 100644 --- a/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java +++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpChannelBuilder.java @@ -23,6 +23,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; +import com.google.errorprone.annotations.CheckReturnValue; import io.grpc.CallCredentials; import io.grpc.ChannelCredentials; import io.grpc.ChannelLogger; @@ -73,7 +74,6 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; -import javax.annotation.CheckReturnValue; import javax.annotation.Nullable; import javax.net.SocketFactory; import javax.net.ssl.HostnameVerifier; diff --git a/okhttp/src/main/java/io/grpc/okhttp/OkHttpClientStream.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpClientStream.java index 9d9fe160715..e33617886cf 100644 --- a/okhttp/src/main/java/io/grpc/okhttp/OkHttpClientStream.java +++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpClientStream.java @@ -21,6 +21,7 @@ import static io.grpc.internal.ClientStreamListener.RpcProgress.PROCESSED; import com.google.common.io.BaseEncoding; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Attributes; import io.grpc.CallOptions; import io.grpc.Metadata; @@ -37,7 +38,6 @@ import io.perfmark.Tag; import io.perfmark.TaskCloseable; import java.util.List; -import javax.annotation.concurrent.GuardedBy; import okio.Buffer; /** diff --git a/okhttp/src/main/java/io/grpc/okhttp/OkHttpClientTransport.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpClientTransport.java index 04a241ad42c..8c69bc390a6 100644 --- a/okhttp/src/main/java/io/grpc/okhttp/OkHttpClientTransport.java +++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpClientTransport.java @@ -27,6 +27,7 @@ import com.google.common.base.Supplier; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Attributes; import io.grpc.CallOptions; import io.grpc.ChannelCredentials; @@ -106,7 +107,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; import javax.net.SocketFactory; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLParameters; @@ -1628,4 +1628,4 @@ public String getPeerHost() { return peerHost; } } -} \ No newline at end of file +} diff --git a/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerStream.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerStream.java index bcf8837b7eb..d1f1a3f4fe0 100644 --- a/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerStream.java +++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerStream.java @@ -17,6 +17,7 @@ package io.grpc.okhttp; import com.google.common.base.Preconditions; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Attributes; import io.grpc.Metadata; import io.grpc.Status; @@ -30,7 +31,6 @@ import io.perfmark.Tag; import io.perfmark.TaskCloseable; import java.util.List; -import javax.annotation.concurrent.GuardedBy; import okio.Buffer; /** diff --git a/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerTransport.java b/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerTransport.java index 2da041f571e..cc52bee85eb 100644 --- a/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerTransport.java +++ b/okhttp/src/main/java/io/grpc/okhttp/OkHttpServerTransport.java @@ -22,6 +22,7 @@ import com.google.common.base.Preconditions; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Attributes; import io.grpc.InternalChannelz; import io.grpc.InternalLogId; @@ -62,7 +63,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; import okio.Buffer; import okio.BufferedSource; import okio.ByteString; diff --git a/okhttp/src/main/java/io/grpc/okhttp/Utils.java b/okhttp/src/main/java/io/grpc/okhttp/Utils.java index 2dc5f1e1ec9..4546143cf3b 100644 --- a/okhttp/src/main/java/io/grpc/okhttp/Utils.java +++ b/okhttp/src/main/java/io/grpc/okhttp/Utils.java @@ -17,6 +17,7 @@ package io.grpc.okhttp; import com.google.common.base.Preconditions; +import com.google.errorprone.annotations.CheckReturnValue; import io.grpc.InternalChannelz; import io.grpc.InternalMetadata; import io.grpc.Metadata; @@ -29,7 +30,6 @@ import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import javax.annotation.CheckReturnValue; /** * Common utility methods for OkHttp transport. diff --git a/okhttp/third_party/okhttp/main/java/io/grpc/okhttp/internal/OkHostnameVerifier.java b/okhttp/third_party/okhttp/main/java/io/grpc/okhttp/internal/OkHostnameVerifier.java index 34bb56ee2d6..f6efb2d90e7 100644 --- a/okhttp/third_party/okhttp/main/java/io/grpc/okhttp/internal/OkHostnameVerifier.java +++ b/okhttp/third_party/okhttp/main/java/io/grpc/okhttp/internal/OkHostnameVerifier.java @@ -29,10 +29,13 @@ import java.util.List; import java.util.Locale; import java.util.regex.Pattern; +import java.nio.charset.StandardCharsets; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLException; import javax.net.ssl.SSLSession; import javax.security.auth.x500.X500Principal; +import com.google.common.base.Utf8; +import com.google.common.base.Ascii; /** * A HostnameVerifier consistent with altNames = getSubjectAltNames(certificate, ALT_DNS_NAME); for (int i = 0, size = altNames.size(); i < size; i++) { @@ -198,7 +204,7 @@ private boolean verifyHostName(String hostName, String pattern) { } // hostName and pattern are now absolute domain names. - pattern = pattern.toLowerCase(Locale.US); + pattern = Ascii.toLowerCase(pattern); // hostName and pattern are now in lower case -- domain names are case-insensitive. if (!pattern.contains("*")) { @@ -254,4 +260,13 @@ private boolean verifyHostName(String hostName, String pattern) { // hostName matches pattern return true; } + + /** + * Returns true if {@code input} is an ASCII string. + * @param input the string to check. + */ + private static boolean isAscii(String input) { + // Only ASCII characters are 1 byte in UTF-8. + return Utf8.encodedLength(input) == input.length(); + } } diff --git a/opentelemetry/build.gradle b/opentelemetry/build.gradle index 00d913c280d..b729f393e4b 100644 --- a/opentelemetry/build.gradle +++ b/opentelemetry/build.gradle @@ -23,8 +23,11 @@ dependencies { annotationProcessor libraries.auto.value - signature libraries.signature.java - signature libraries.signature.android + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } } tasks.named("jar").configure { diff --git a/opentelemetry/src/main/java/io/grpc/opentelemetry/OpenTelemetryMetricsModule.java b/opentelemetry/src/main/java/io/grpc/opentelemetry/OpenTelemetryMetricsModule.java index f631da59d01..b6cf09d9db6 100644 --- a/opentelemetry/src/main/java/io/grpc/opentelemetry/OpenTelemetryMetricsModule.java +++ b/opentelemetry/src/main/java/io/grpc/opentelemetry/OpenTelemetryMetricsModule.java @@ -27,6 +27,7 @@ import com.google.common.base.Supplier; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.CallOptions; import io.grpc.Channel; import io.grpc.ClientCall; @@ -54,7 +55,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; /** * Provides factories for {@link StreamTracer} that records metrics to OpenTelemetry. diff --git a/protobuf-lite/build.gradle b/protobuf-lite/build.gradle index 11a49d4816d..16b622535e8 100644 --- a/protobuf-lite/build.gradle +++ b/protobuf-lite/build.gradle @@ -17,8 +17,16 @@ dependencies { testImplementation project(':grpc-core') - signature libraries.signature.java - signature libraries.signature.android + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } + signature (libraries.signature.android) { + artifact { + extension = "signature" + } + } } tasks.named("jar").configure { diff --git a/protobuf/BUILD.bazel b/protobuf/BUILD.bazel index 724c78ca6ee..02a136554d2 100644 --- a/protobuf/BUILD.bazel +++ b/protobuf/BUILD.bazel @@ -12,6 +12,7 @@ java_library( "@com_google_protobuf//:protobuf_java", artifact("com.google.api.grpc:proto-google-common-protos"), artifact("com.google.code.findbugs:jsr305"), + artifact("com.google.errorprone:error_prone_annotations"), artifact("com.google.guava:guava"), ], ) diff --git a/protobuf/build.gradle b/protobuf/build.gradle index c88ae836e0f..c477e41dceb 100644 --- a/protobuf/build.gradle +++ b/protobuf/build.gradle @@ -31,8 +31,16 @@ dependencies { exclude group: 'com.google.protobuf', module: 'protobuf-javalite' } - signature libraries.signature.java - signature libraries.signature.android + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } + signature (libraries.signature.android) { + artifact { + extension = "signature" + } + } } tasks.named("javadoc").configure { diff --git a/protobuf/src/main/java/io/grpc/protobuf/ProtoMethodDescriptorSupplier.java b/protobuf/src/main/java/io/grpc/protobuf/ProtoMethodDescriptorSupplier.java index e5b2f38e3c0..e7cd3ed336f 100644 --- a/protobuf/src/main/java/io/grpc/protobuf/ProtoMethodDescriptorSupplier.java +++ b/protobuf/src/main/java/io/grpc/protobuf/ProtoMethodDescriptorSupplier.java @@ -16,8 +16,8 @@ package io.grpc.protobuf; +import com.google.errorprone.annotations.CheckReturnValue; import com.google.protobuf.Descriptors.MethodDescriptor; -import javax.annotation.CheckReturnValue; /** * Provides access to the underlying proto service method descriptor. diff --git a/rls/BUILD.bazel b/rls/BUILD.bazel index 10a5e22524a..bfa0c7eee97 100644 --- a/rls/BUILD.bazel +++ b/rls/BUILD.bazel @@ -19,6 +19,7 @@ java_library( "@io_grpc_grpc_proto//:rls_java_proto", artifact("com.google.auto.value:auto-value-annotations"), artifact("com.google.code.findbugs:jsr305"), + artifact("com.google.errorprone:error_prone_annotations"), artifact("com.google.guava:guava"), ], ) diff --git a/rls/build.gradle b/rls/build.gradle index 0629dce64c1..1dbcd91ec3c 100644 --- a/rls/build.gradle +++ b/rls/build.gradle @@ -30,7 +30,11 @@ dependencies { project(':grpc-testing-proto'), testFixtures(project(':grpc-api')), testFixtures(project(':grpc-core')) - signature libraries.signature.java + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } } tasks.named("compileJava").configure { diff --git a/rls/src/generated/main/grpc/io/grpc/lookup/v1/RouteLookupServiceGrpc.java b/rls/src/generated/main/grpc/io/grpc/lookup/v1/RouteLookupServiceGrpc.java index d7334b942ff..558a223173c 100644 --- a/rls/src/generated/main/grpc/io/grpc/lookup/v1/RouteLookupServiceGrpc.java +++ b/rls/src/generated/main/grpc/io/grpc/lookup/v1/RouteLookupServiceGrpc.java @@ -60,6 +60,21 @@ public RouteLookupServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptio return RouteLookupServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static RouteLookupServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public RouteLookupServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new RouteLookupServiceBlockingV2Stub(channel, callOptions); + } + }; + return RouteLookupServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -147,6 +162,33 @@ public void routeLookup(io.grpc.lookup.v1.RouteLookupRequest request, /** * A stub to allow clients to do synchronous rpc calls to service RouteLookupService. */ + public static final class RouteLookupServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private RouteLookupServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected RouteLookupServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new RouteLookupServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * Lookup returns a target for a single key.
+     * 
+ */ + public io.grpc.lookup.v1.RouteLookupResponse routeLookup(io.grpc.lookup.v1.RouteLookupRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getRouteLookupMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service RouteLookupService. + */ public static final class RouteLookupServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private RouteLookupServiceBlockingStub( diff --git a/rls/src/main/java/io/grpc/rls/CachingRlsLbClient.java b/rls/src/main/java/io/grpc/rls/CachingRlsLbClient.java index 3d52187a158..70833416d5d 100644 --- a/rls/src/main/java/io/grpc/rls/CachingRlsLbClient.java +++ b/rls/src/main/java/io/grpc/rls/CachingRlsLbClient.java @@ -28,6 +28,8 @@ import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.SettableFuture; +import com.google.errorprone.annotations.CheckReturnValue; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.ChannelLogger; import io.grpc.ChannelLogger.ChannelLogLevel; import io.grpc.ConnectivityState; @@ -73,9 +75,7 @@ import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import javax.annotation.CheckReturnValue; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.ThreadSafe; /** diff --git a/rls/src/main/java/io/grpc/rls/LinkedHashLruCache.java b/rls/src/main/java/io/grpc/rls/LinkedHashLruCache.java index ba0575efa57..b39b463c762 100644 --- a/rls/src/main/java/io/grpc/rls/LinkedHashLruCache.java +++ b/rls/src/main/java/io/grpc/rls/LinkedHashLruCache.java @@ -22,6 +22,7 @@ import com.google.common.base.MoreObjects; import com.google.common.base.Ticker; +import com.google.errorprone.annotations.CheckReturnValue; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; @@ -29,7 +30,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import javax.annotation.CheckReturnValue; import javax.annotation.Nullable; /** diff --git a/rls/src/main/java/io/grpc/rls/LruCache.java b/rls/src/main/java/io/grpc/rls/LruCache.java index 1ad5a958289..8fc4ae98472 100644 --- a/rls/src/main/java/io/grpc/rls/LruCache.java +++ b/rls/src/main/java/io/grpc/rls/LruCache.java @@ -16,7 +16,7 @@ package io.grpc.rls; -import javax.annotation.CheckReturnValue; +import com.google.errorprone.annotations.CheckReturnValue; import javax.annotation.Nullable; /** An LruCache is a cache with least recently used eviction. */ diff --git a/rls/src/main/java/io/grpc/rls/RlsRequestFactory.java b/rls/src/main/java/io/grpc/rls/RlsRequestFactory.java index a6ca0137ff1..e26e49979e1 100644 --- a/rls/src/main/java/io/grpc/rls/RlsRequestFactory.java +++ b/rls/src/main/java/io/grpc/rls/RlsRequestFactory.java @@ -20,6 +20,7 @@ import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableMap; +import com.google.errorprone.annotations.CheckReturnValue; import io.grpc.Metadata; import io.grpc.rls.RlsProtoData.ExtraKeys; import io.grpc.rls.RlsProtoData.GrpcKeyBuilder; @@ -30,7 +31,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.annotation.CheckReturnValue; /** * A RlsRequestFactory creates {@link RouteLookupRequest} using key builder map from {@link diff --git a/s2a/build.gradle b/s2a/build.gradle index 572c48a0c5b..6ac193938ca 100644 --- a/s2a/build.gradle +++ b/s2a/build.gradle @@ -62,7 +62,11 @@ dependencies { } } - signature libraries.signature.java + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } } configureProtoCompilation() diff --git a/s2a/src/generated/main/grpc/io/grpc/s2a/internal/handshaker/S2AServiceGrpc.java b/s2a/src/generated/main/grpc/io/grpc/s2a/internal/handshaker/S2AServiceGrpc.java index d759128a4c5..95e217ac695 100644 --- a/s2a/src/generated/main/grpc/io/grpc/s2a/internal/handshaker/S2AServiceGrpc.java +++ b/s2a/src/generated/main/grpc/io/grpc/s2a/internal/handshaker/S2AServiceGrpc.java @@ -60,6 +60,21 @@ public S2AServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callO return S2AServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static S2AServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public S2AServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new S2AServiceBlockingV2Stub(channel, callOptions); + } + }; + return S2AServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -149,6 +164,36 @@ public io.grpc.stub.StreamObserver s /** * A stub to allow clients to do synchronous rpc calls to service S2AService. */ + public static final class S2AServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private S2AServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected S2AServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new S2AServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * SetUpSession is a bidirectional stream used by applications to offload
+     * operations from the TLS handshake.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + setUpSession() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getSetUpSessionMethod(), getCallOptions()); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service S2AService. + */ public static final class S2AServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private S2AServiceBlockingStub( diff --git a/s2a/src/main/java/io/grpc/s2a/internal/handshaker/S2AProtocolNegotiatorFactory.java b/s2a/src/main/java/io/grpc/s2a/internal/handshaker/S2AProtocolNegotiatorFactory.java index 7ad9de991cf..0822399aad6 100644 --- a/s2a/src/main/java/io/grpc/s2a/internal/handshaker/S2AProtocolNegotiatorFactory.java +++ b/s2a/src/main/java/io/grpc/s2a/internal/handshaker/S2AProtocolNegotiatorFactory.java @@ -253,7 +253,7 @@ public void onSuccess(SslContext sslContext) { InternalProtocolNegotiators.tls( sslContext, SharedResourcePool.forResource(GrpcUtil.SHARED_CHANNEL_EXECUTOR), - Optional.of(new Runnable() { + com.google.common.base.Optional.of(new Runnable() { @Override public void run() { s2aStub.close(); @@ -278,4 +278,4 @@ public void onFailure(Throwable t) { } private S2AProtocolNegotiatorFactory() {} -} \ No newline at end of file +} diff --git a/services/BUILD.bazel b/services/BUILD.bazel index d20e956ed49..9ac894ffaee 100644 --- a/services/BUILD.bazel +++ b/services/BUILD.bazel @@ -121,6 +121,7 @@ java_library( "@io_grpc_grpc_proto//:reflection_java_proto", "@io_grpc_grpc_proto//:reflection_java_proto_deprecated", artifact("com.google.code.findbugs:jsr305"), + artifact("com.google.errorprone:error_prone_annotations"), artifact("com.google.guava:guava"), ], ) @@ -139,6 +140,7 @@ java_library( "//stub", "@io_grpc_grpc_proto//:health_java_proto", artifact("com.google.code.findbugs:jsr305"), + artifact("com.google.errorprone:error_prone_annotations"), artifact("com.google.guava:guava"), ], ) diff --git a/services/build.gradle b/services/build.gradle index 6daa7b0511d..758f2a5c899 100644 --- a/services/build.gradle +++ b/services/build.gradle @@ -39,7 +39,11 @@ dependencies { testFixtures(project(':grpc-core')), testFixtures(project(':grpc-api')) testCompileOnly libraries.javax.annotation - signature libraries.signature.java + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } } configureProtoCompilation() diff --git a/services/src/generated/main/grpc/io/grpc/channelz/v1/ChannelzGrpc.java b/services/src/generated/main/grpc/io/grpc/channelz/v1/ChannelzGrpc.java index b3c1c285c8f..7dd74034efe 100644 --- a/services/src/generated/main/grpc/io/grpc/channelz/v1/ChannelzGrpc.java +++ b/services/src/generated/main/grpc/io/grpc/channelz/v1/ChannelzGrpc.java @@ -250,6 +250,21 @@ public ChannelzStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOpt return ChannelzStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static ChannelzBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public ChannelzBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new ChannelzBlockingV2Stub(channel, callOptions); + } + }; + return ChannelzBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -481,6 +496,98 @@ public void getSocket(io.grpc.channelz.v1.GetSocketRequest request, * information. * */ + public static final class ChannelzBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private ChannelzBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected ChannelzBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new ChannelzBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * Gets all root channels (i.e. channels the application has directly
+     * created). This does not include subchannels nor non-top level channels.
+     * 
+ */ + public io.grpc.channelz.v1.GetTopChannelsResponse getTopChannels(io.grpc.channelz.v1.GetTopChannelsRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getGetTopChannelsMethod(), getCallOptions(), request); + } + + /** + *
+     * Gets all servers that exist in the process.
+     * 
+ */ + public io.grpc.channelz.v1.GetServersResponse getServers(io.grpc.channelz.v1.GetServersRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getGetServersMethod(), getCallOptions(), request); + } + + /** + *
+     * Returns a single Server, or else a NOT_FOUND code.
+     * 
+ */ + public io.grpc.channelz.v1.GetServerResponse getServer(io.grpc.channelz.v1.GetServerRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getGetServerMethod(), getCallOptions(), request); + } + + /** + *
+     * Gets all server sockets that exist in the process.
+     * 
+ */ + public io.grpc.channelz.v1.GetServerSocketsResponse getServerSockets(io.grpc.channelz.v1.GetServerSocketsRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getGetServerSocketsMethod(), getCallOptions(), request); + } + + /** + *
+     * Returns a single Channel, or else a NOT_FOUND code.
+     * 
+ */ + public io.grpc.channelz.v1.GetChannelResponse getChannel(io.grpc.channelz.v1.GetChannelRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getGetChannelMethod(), getCallOptions(), request); + } + + /** + *
+     * Returns a single Subchannel, or else a NOT_FOUND code.
+     * 
+ */ + public io.grpc.channelz.v1.GetSubchannelResponse getSubchannel(io.grpc.channelz.v1.GetSubchannelRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getGetSubchannelMethod(), getCallOptions(), request); + } + + /** + *
+     * Returns a single Socket or else a NOT_FOUND code.
+     * 
+ */ + public io.grpc.channelz.v1.GetSocketResponse getSocket(io.grpc.channelz.v1.GetSocketRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getGetSocketMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service Channelz. + *
+   * Channelz is a service exposed by gRPC servers that provides detailed debug
+   * information.
+   * 
+ */ public static final class ChannelzBlockingStub extends io.grpc.stub.AbstractBlockingStub { private ChannelzBlockingStub( diff --git a/services/src/generated/main/grpc/io/grpc/health/v1/HealthGrpc.java b/services/src/generated/main/grpc/io/grpc/health/v1/HealthGrpc.java index 73ddd4e0d23..9786392cfe6 100644 --- a/services/src/generated/main/grpc/io/grpc/health/v1/HealthGrpc.java +++ b/services/src/generated/main/grpc/io/grpc/health/v1/HealthGrpc.java @@ -91,6 +91,21 @@ public HealthStub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptio return HealthStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static HealthBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public HealthBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new HealthBlockingV2Stub(channel, callOptions); + } + }; + return HealthBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -225,6 +240,58 @@ public void watch(io.grpc.health.v1.HealthCheckRequest request, /** * A stub to allow clients to do synchronous rpc calls to service Health. */ + public static final class HealthBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private HealthBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected HealthBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new HealthBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * If the requested service is unknown, the call will fail with status
+     * NOT_FOUND.
+     * 
+ */ + public io.grpc.health.v1.HealthCheckResponse check(io.grpc.health.v1.HealthCheckRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getCheckMethod(), getCallOptions(), request); + } + + /** + *
+     * Performs a watch for the serving status of the requested service.
+     * The server will immediately send back a message indicating the current
+     * serving status.  It will then subsequently send a new message whenever
+     * the service's serving status changes.
+     * If the requested service is unknown when the call is received, the
+     * server will send a message setting the serving status to
+     * SERVICE_UNKNOWN but will *not* terminate the call.  If at some
+     * future point, the serving status of the service becomes known, the
+     * server will send a new message with the service's serving status.
+     * If the call terminates with status UNIMPLEMENTED, then clients
+     * should assume this method is not supported and should not retry the
+     * call.  If the call terminates with any other status (including OK),
+     * clients should retry the call with appropriate exponential backoff.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + watch(io.grpc.health.v1.HealthCheckRequest request) { + return io.grpc.stub.ClientCalls.blockingV2ServerStreamingCall( + getChannel(), getWatchMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service Health. + */ public static final class HealthBlockingStub extends io.grpc.stub.AbstractBlockingStub { private HealthBlockingStub( diff --git a/services/src/generated/main/grpc/io/grpc/reflection/v1/ServerReflectionGrpc.java b/services/src/generated/main/grpc/io/grpc/reflection/v1/ServerReflectionGrpc.java index 4f2dce26486..19bf6ed90b3 100644 --- a/services/src/generated/main/grpc/io/grpc/reflection/v1/ServerReflectionGrpc.java +++ b/services/src/generated/main/grpc/io/grpc/reflection/v1/ServerReflectionGrpc.java @@ -60,6 +60,21 @@ public ServerReflectionStub newStub(io.grpc.Channel channel, io.grpc.CallOptions return ServerReflectionStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static ServerReflectionBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public ServerReflectionBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new ServerReflectionBlockingV2Stub(channel, callOptions); + } + }; + return ServerReflectionBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -149,6 +164,36 @@ public io.grpc.stub.StreamObserver { + private ServerReflectionBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected ServerReflectionBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new ServerReflectionBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * The reflection service is structured as a bidirectional stream, ensuring
+     * all related requests go to a single server.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + serverReflectionInfo() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getServerReflectionInfoMethod(), getCallOptions()); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service ServerReflection. + */ public static final class ServerReflectionBlockingStub extends io.grpc.stub.AbstractBlockingStub { private ServerReflectionBlockingStub( diff --git a/services/src/generated/main/grpc/io/grpc/reflection/v1alpha/ServerReflectionGrpc.java b/services/src/generated/main/grpc/io/grpc/reflection/v1alpha/ServerReflectionGrpc.java index 7119e96d1f3..152a8f7c81d 100644 --- a/services/src/generated/main/grpc/io/grpc/reflection/v1alpha/ServerReflectionGrpc.java +++ b/services/src/generated/main/grpc/io/grpc/reflection/v1alpha/ServerReflectionGrpc.java @@ -60,6 +60,21 @@ public ServerReflectionStub newStub(io.grpc.Channel channel, io.grpc.CallOptions return ServerReflectionStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static ServerReflectionBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public ServerReflectionBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new ServerReflectionBlockingV2Stub(channel, callOptions); + } + }; + return ServerReflectionBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -149,6 +164,36 @@ public io.grpc.stub.StreamObserver { + private ServerReflectionBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected ServerReflectionBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new ServerReflectionBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * The reflection service is structured as a bidirectional stream, ensuring
+     * all related requests go to a single server.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + serverReflectionInfo() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getServerReflectionInfoMethod(), getCallOptions()); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service ServerReflection. + */ public static final class ServerReflectionBlockingStub extends io.grpc.stub.AbstractBlockingStub { private ServerReflectionBlockingStub( diff --git a/services/src/generated/test/grpc/io/grpc/reflection/testing/AnotherDynamicServiceGrpc.java b/services/src/generated/test/grpc/io/grpc/reflection/testing/AnotherDynamicServiceGrpc.java index 088d27b619c..a53d199ef52 100644 --- a/services/src/generated/test/grpc/io/grpc/reflection/testing/AnotherDynamicServiceGrpc.java +++ b/services/src/generated/test/grpc/io/grpc/reflection/testing/AnotherDynamicServiceGrpc.java @@ -63,6 +63,21 @@ public AnotherDynamicServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOp return AnotherDynamicServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static AnotherDynamicServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public AnotherDynamicServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new AnotherDynamicServiceBlockingV2Stub(channel, callOptions); + } + }; + return AnotherDynamicServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -162,6 +177,36 @@ public void method(io.grpc.reflection.testing.DynamicRequest request, * AnotherDynamicService * */ + public static final class AnotherDynamicServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private AnotherDynamicServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected AnotherDynamicServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new AnotherDynamicServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * A method
+     * 
+ */ + public io.grpc.reflection.testing.DynamicReply method(io.grpc.reflection.testing.DynamicRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getMethodMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service AnotherDynamicService. + *
+   * AnotherDynamicService
+   * 
+ */ public static final class AnotherDynamicServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private AnotherDynamicServiceBlockingStub( diff --git a/services/src/generated/test/grpc/io/grpc/reflection/testing/AnotherReflectableServiceGrpc.java b/services/src/generated/test/grpc/io/grpc/reflection/testing/AnotherReflectableServiceGrpc.java index a84b95b2126..a22138ecb03 100644 --- a/services/src/generated/test/grpc/io/grpc/reflection/testing/AnotherReflectableServiceGrpc.java +++ b/services/src/generated/test/grpc/io/grpc/reflection/testing/AnotherReflectableServiceGrpc.java @@ -60,6 +60,21 @@ public AnotherReflectableServiceStub newStub(io.grpc.Channel channel, io.grpc.Ca return AnotherReflectableServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static AnotherReflectableServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public AnotherReflectableServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new AnotherReflectableServiceBlockingV2Stub(channel, callOptions); + } + }; + return AnotherReflectableServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -141,6 +156,30 @@ public void method(io.grpc.reflection.testing.Request request, /** * A stub to allow clients to do synchronous rpc calls to service AnotherReflectableService. */ + public static final class AnotherReflectableServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private AnotherReflectableServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected AnotherReflectableServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new AnotherReflectableServiceBlockingV2Stub(channel, callOptions); + } + + /** + */ + public io.grpc.reflection.testing.Reply method(io.grpc.reflection.testing.Request request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getMethodMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service AnotherReflectableService. + */ public static final class AnotherReflectableServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private AnotherReflectableServiceBlockingStub( diff --git a/services/src/generated/test/grpc/io/grpc/reflection/testing/DynamicServiceGrpc.java b/services/src/generated/test/grpc/io/grpc/reflection/testing/DynamicServiceGrpc.java index 338b67e684d..6e9dfac72db 100644 --- a/services/src/generated/test/grpc/io/grpc/reflection/testing/DynamicServiceGrpc.java +++ b/services/src/generated/test/grpc/io/grpc/reflection/testing/DynamicServiceGrpc.java @@ -63,6 +63,21 @@ public DynamicServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions c return DynamicServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static DynamicServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public DynamicServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new DynamicServiceBlockingV2Stub(channel, callOptions); + } + }; + return DynamicServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -162,6 +177,36 @@ public void method(io.grpc.reflection.testing.DynamicRequest request, * A DynamicService * */ + public static final class DynamicServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private DynamicServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected DynamicServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new DynamicServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * A method
+     * 
+ */ + public io.grpc.reflection.testing.DynamicReply method(io.grpc.reflection.testing.DynamicRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getMethodMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service DynamicService. + *
+   * A DynamicService
+   * 
+ */ public static final class DynamicServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private DynamicServiceBlockingStub( diff --git a/services/src/generated/test/grpc/io/grpc/reflection/testing/ReflectableServiceGrpc.java b/services/src/generated/test/grpc/io/grpc/reflection/testing/ReflectableServiceGrpc.java index 0b8954b5eb9..aeefc77aff8 100644 --- a/services/src/generated/test/grpc/io/grpc/reflection/testing/ReflectableServiceGrpc.java +++ b/services/src/generated/test/grpc/io/grpc/reflection/testing/ReflectableServiceGrpc.java @@ -60,6 +60,21 @@ public ReflectableServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptio return ReflectableServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static ReflectableServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public ReflectableServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new ReflectableServiceBlockingV2Stub(channel, callOptions); + } + }; + return ReflectableServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -141,6 +156,30 @@ public void method(io.grpc.reflection.testing.Request request, /** * A stub to allow clients to do synchronous rpc calls to service ReflectableService. */ + public static final class ReflectableServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private ReflectableServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected ReflectableServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new ReflectableServiceBlockingV2Stub(channel, callOptions); + } + + /** + */ + public io.grpc.reflection.testing.Reply method(io.grpc.reflection.testing.Request request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getMethodMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service ReflectableService. + */ public static final class ReflectableServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private ReflectableServiceBlockingStub( diff --git a/services/src/main/java/io/grpc/protobuf/services/HealthServiceImpl.java b/services/src/main/java/io/grpc/protobuf/services/HealthServiceImpl.java index 6ce602b9295..2efe4b3951a 100644 --- a/services/src/main/java/io/grpc/protobuf/services/HealthServiceImpl.java +++ b/services/src/main/java/io/grpc/protobuf/services/HealthServiceImpl.java @@ -18,6 +18,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.util.concurrent.MoreExecutors; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.Context; import io.grpc.Context.CancellationListener; import io.grpc.Status; @@ -34,7 +35,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; final class HealthServiceImpl extends HealthGrpc.HealthImplBase { diff --git a/services/src/main/java/io/grpc/protobuf/services/ProtoReflectionServiceV1.java b/services/src/main/java/io/grpc/protobuf/services/ProtoReflectionServiceV1.java index 578e9bbd409..59e9c33d279 100644 --- a/services/src/main/java/io/grpc/protobuf/services/ProtoReflectionServiceV1.java +++ b/services/src/main/java/io/grpc/protobuf/services/ProtoReflectionServiceV1.java @@ -19,6 +19,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; +import com.google.errorprone.annotations.concurrent.GuardedBy; import com.google.protobuf.Descriptors.Descriptor; import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.Descriptors.FileDescriptor; @@ -52,7 +53,6 @@ import java.util.Set; import java.util.WeakHashMap; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; /** * Provides a reflection service for Protobuf services (including the reflection service itself). diff --git a/servlet/src/main/java/io/grpc/servlet/AsyncServletOutputStreamWriter.java b/servlet/src/main/java/io/grpc/servlet/AsyncServletOutputStreamWriter.java index cfd29b1a2fd..8c0c6ec6512 100644 --- a/servlet/src/main/java/io/grpc/servlet/AsyncServletOutputStreamWriter.java +++ b/servlet/src/main/java/io/grpc/servlet/AsyncServletOutputStreamWriter.java @@ -22,6 +22,7 @@ import static java.util.logging.Level.FINEST; import com.google.common.annotations.VisibleForTesting; +import com.google.errorprone.annotations.CheckReturnValue; import io.grpc.InternalLogId; import io.grpc.servlet.ServletServerStream.ServletTransportState; import java.io.IOException; @@ -34,7 +35,6 @@ import java.util.function.BooleanSupplier; import java.util.logging.Level; import java.util.logging.Logger; -import javax.annotation.CheckReturnValue; import javax.annotation.Nullable; import javax.servlet.AsyncContext; import javax.servlet.ServletOutputStream; diff --git a/stub/BUILD.bazel b/stub/BUILD.bazel index 6d06e01f918..572ea681ef3 100644 --- a/stub/BUILD.bazel +++ b/stub/BUILD.bazel @@ -12,6 +12,7 @@ java_library( artifact("com.google.code.findbugs:jsr305"), artifact("com.google.errorprone:error_prone_annotations"), artifact("com.google.guava:guava"), + artifact("org.codehaus.mojo:animal-sniffer-annotations"), ], ) diff --git a/stub/build.gradle b/stub/build.gradle index 867936f3ea3..2dabd9e6202 100644 --- a/stub/build.gradle +++ b/stub/build.gradle @@ -16,14 +16,23 @@ tasks.named("jar").configure { dependencies { api project(':grpc-api'), + libraries.animalsniffer.annotations, libraries.guava implementation libraries.errorprone.annotations testImplementation libraries.truth, project(':grpc-inprocess'), project(':grpc-testing'), testFixtures(project(':grpc-api')) - signature libraries.signature.java - signature libraries.signature.android + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } + signature (libraries.signature.android) { + artifact { + extension = "signature" + } + } } tasks.named("javadoc").configure { diff --git a/stub/src/main/java/io/grpc/stub/AbstractAsyncStub.java b/stub/src/main/java/io/grpc/stub/AbstractAsyncStub.java index c6f912cb3a7..f369eeaf87f 100644 --- a/stub/src/main/java/io/grpc/stub/AbstractAsyncStub.java +++ b/stub/src/main/java/io/grpc/stub/AbstractAsyncStub.java @@ -16,10 +16,10 @@ package io.grpc.stub; +import com.google.errorprone.annotations.CheckReturnValue; import io.grpc.CallOptions; import io.grpc.Channel; import io.grpc.stub.ClientCalls.StubType; -import javax.annotation.CheckReturnValue; import javax.annotation.concurrent.ThreadSafe; /** diff --git a/stub/src/main/java/io/grpc/stub/AbstractBlockingStub.java b/stub/src/main/java/io/grpc/stub/AbstractBlockingStub.java index 1cb919e67b0..4bdb3c0bb94 100644 --- a/stub/src/main/java/io/grpc/stub/AbstractBlockingStub.java +++ b/stub/src/main/java/io/grpc/stub/AbstractBlockingStub.java @@ -16,10 +16,10 @@ package io.grpc.stub; +import com.google.errorprone.annotations.CheckReturnValue; import io.grpc.CallOptions; import io.grpc.Channel; import io.grpc.stub.ClientCalls.StubType; -import javax.annotation.CheckReturnValue; import javax.annotation.concurrent.ThreadSafe; /** diff --git a/stub/src/main/java/io/grpc/stub/AbstractFutureStub.java b/stub/src/main/java/io/grpc/stub/AbstractFutureStub.java index 66570bcd6ff..5e37b1e4915 100644 --- a/stub/src/main/java/io/grpc/stub/AbstractFutureStub.java +++ b/stub/src/main/java/io/grpc/stub/AbstractFutureStub.java @@ -16,10 +16,10 @@ package io.grpc.stub; +import com.google.errorprone.annotations.CheckReturnValue; import io.grpc.CallOptions; import io.grpc.Channel; import io.grpc.stub.ClientCalls.StubType; -import javax.annotation.CheckReturnValue; import javax.annotation.concurrent.ThreadSafe; /** diff --git a/stub/src/main/java/io/grpc/stub/AbstractStub.java b/stub/src/main/java/io/grpc/stub/AbstractStub.java index 06dd55ff466..697107760db 100644 --- a/stub/src/main/java/io/grpc/stub/AbstractStub.java +++ b/stub/src/main/java/io/grpc/stub/AbstractStub.java @@ -19,6 +19,7 @@ import static com.google.common.base.Preconditions.checkNotNull; import static io.grpc.InternalTimeUtils.convert; +import com.google.errorprone.annotations.CheckReturnValue; import io.grpc.CallCredentials; import io.grpc.CallOptions; import io.grpc.Channel; @@ -30,9 +31,9 @@ import java.time.Duration; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; -import javax.annotation.CheckReturnValue; import javax.annotation.Nullable; import javax.annotation.concurrent.ThreadSafe; +import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement; /** * Common base type for stub implementations. Stub configuration is immutable; changing the @@ -152,6 +153,7 @@ public final S withDeadlineAfter(long duration, TimeUnit unit) { } @ExperimentalApi("https://github.com/grpc/grpc-java/issues/11657") + @IgnoreJRERequirement public final S withDeadlineAfter(Duration duration) { return withDeadlineAfter(convert(duration), TimeUnit.NANOSECONDS); } diff --git a/stub/src/main/java/io/grpc/stub/BlockingClientCall.java b/stub/src/main/java/io/grpc/stub/BlockingClientCall.java new file mode 100644 index 00000000000..58881ef0592 --- /dev/null +++ b/stub/src/main/java/io/grpc/stub/BlockingClientCall.java @@ -0,0 +1,352 @@ +/* + * Copyright 2023 The gRPC Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc.stub; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import io.grpc.ClientCall; +import io.grpc.ExperimentalApi; +import io.grpc.Metadata; +import io.grpc.Status; +import io.grpc.StatusException; +import io.grpc.stub.ClientCalls.ThreadSafeThreadlessExecutor; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Represents a bidirectional streaming call from a client. Allows in a blocking manner, sending + * over the stream and receiving from the stream. Also supports terminating the call. + * Wraps a ClientCall and converts from async communication to the sync paradigm used by the + * various blocking stream methods in {@link ClientCalls} which are used by the generated stubs. + * + *

Supports separate threads for reads and writes, but only 1 of each + * + *

Read methods consist of: + *

    + *
  • {@link #read()} + *
  • {@link #read(long timeout, TimeUnit unit)} + *
  • {@link #hasNext()} + *
  • {@link #cancel(String, Throwable)} + *
+ * + *

Write methods consist of: + *

    + *
  • {@link #write(Object)} + *
  • {@link #write(Object, long timeout, TimeUnit unit)} + *
  • {@link #halfClose()} + *
+ * + * @param Type of the Request Message + * @param Type of the Response Message + */ +@ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") +public final class BlockingClientCall { + + private static final Logger logger = Logger.getLogger(BlockingClientCall.class.getName()); + + private final BlockingQueue buffer; + private final ClientCall call; + + private final ThreadSafeThreadlessExecutor executor; + + private boolean writeClosed; + private volatile Status closedStatus; // null if not closed + + BlockingClientCall(ClientCall call, ThreadSafeThreadlessExecutor executor) { + this.call = call; + this.executor = executor; + buffer = new ArrayBlockingQueue<>(1); + } + + /** + * Wait if necessary for a value to be available from the server. If there is an available value + * return it immediately, if the stream is closed return a null. Otherwise, wait for a value to be + * available or the stream to be closed + * + * @return value from server or null if stream has been closed + * @throws StatusException If the stream has closed in an error state + */ + public RespT read() throws InterruptedException, StatusException { + try { + return read(true, 0, TimeUnit.NANOSECONDS); + } catch (TimeoutException e) { + throw new AssertionError("should never happen", e); + } + } + + /** + * Wait with timeout, if necessary, for a value to be available from the server. If there is an + * available value, return it immediately. If the stream is closed return a null. Otherwise, wait + * for a value to be available, the stream to be closed or the timeout to expire. + * + * @param timeout how long to wait before giving up. Values <= 0 are no wait + * @param unit a TimeUnit determining how to interpret the timeout parameter + * @return value from server or null (if stream has been closed) + * @throws TimeoutException if no read becomes ready before the specified timeout expires + * @throws StatusException If the stream has closed in an error state + */ + public RespT read(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException, + StatusException { + return read(false, timeout, unit); + } + + private RespT read(boolean waitForever, long timeout, TimeUnit unit) + throws InterruptedException, TimeoutException, StatusException { + long start = System.nanoTime(); + long end = start + unit.toNanos(timeout); + + Predicate> predicate = BlockingClientCall::skipWaitingForRead; + executor.waitAndDrainWithTimeout(waitForever, end, predicate, this); + RespT bufferedValue = buffer.poll(); + + if (logger.isLoggable(Level.FINER)) { + logger.finer("Client Blocking read had value: " + bufferedValue); + } + + Status currentClosedStatus; + if (bufferedValue != null) { + call.request(1); + return bufferedValue; + } else if ((currentClosedStatus = closedStatus) == null) { + throw new IllegalStateException( + "The message disappeared... are you reading from multiple threads?"); + } else if (!currentClosedStatus.isOk()) { + throw currentClosedStatus.asException(); + } else { + return null; + } + } + + boolean skipWaitingForRead() { + return closedStatus != null || !buffer.isEmpty(); + } + + /** + * Wait for a value to be available from the server. If there is an + * available value, return true immediately. If the stream was closed with Status.OK, return + * false. If the stream was closed with an error status, throw a StatusException. Otherwise, wait + * for a value to be available or the stream to be closed. + * + * @return True when there is a value to read. Return false if stream closed cleanly. + * @throws StatusException If the stream was closed in an error state + */ + public boolean hasNext() throws InterruptedException, StatusException { + executor.waitAndDrain((x) -> !x.buffer.isEmpty() || x.closedStatus != null, this); + + Status currentClosedStatus = closedStatus; + if (currentClosedStatus != null && !currentClosedStatus.isOk()) { + throw currentClosedStatus.asException(); + } + + return !buffer.isEmpty(); + } + + /** + * Send a value to the stream for sending to server, wait if necessary for the grpc stream to be + * ready. + * + *

If write is not legal at the time of call, immediately returns false + * + *


NOTE: This method will return as soon as it passes the request to the grpc stream + * layer. It will not block while the message is being sent on the wire and returning true does + * not guarantee that the server gets the message. + * + *


WARNING: Doing only writes without reads can lead to deadlocks. This is because + * flow control, imposed by networks to protect intermediary routers and endpoints that are + * operating under resource constraints, requires reads to be done in order to progress writes. + * Furthermore, the server closing the stream will only be identified after + * the last sent value is read. + * + * @param request Message to send to the server + * @return true if the request is sent to stream, false if skipped + * @throws StatusException If the stream has closed in an error state + */ + public boolean write(ReqT request) throws InterruptedException, StatusException { + try { + return write(true, request, Integer.MAX_VALUE, TimeUnit.DAYS); + } catch (TimeoutException e) { + throw new RuntimeException(e); // should never happen + } + } + + /** + * Send a value to the stream for sending to server, wait if necessary for the grpc stream to be + * ready up to specified timeout. + * + *

If write is not legal at the time of call, immediately returns false + * + *


NOTE: This method will return as soon as it passes the request to the grpc stream + * layer. It will not block while the message is being sent on the wire and returning true does + * not guarantee that the server gets the message. + * + *


WARNING: Doing only writes without reads can lead to deadlocks as a result of + * flow control. Furthermore, the server closing the stream will only be identified after the + * last sent value is read. + * + * @param request Message to send to the server + * @param timeout How long to wait before giving up. Values <= 0 are no wait + * @param unit A TimeUnit determining how to interpret the timeout parameter + * @return true if the request is sent to stream, false if skipped + * @throws TimeoutException if write does not become ready before the specified timeout expires + * @throws StatusException If the stream has closed in an error state + */ + public boolean write(ReqT request, long timeout, TimeUnit unit) + throws InterruptedException, TimeoutException, StatusException { + return write(false, request, timeout, unit); + } + + private boolean write(boolean waitForever, ReqT request, long timeout, TimeUnit unit) + throws InterruptedException, TimeoutException, StatusException { + + if (writeClosed) { + throw new IllegalStateException("Writes cannot be done after calling halfClose or cancel"); + } + + long end = System.nanoTime() + unit.toNanos(timeout); + + Predicate> predicate = + (x) -> x.call.isReady() || x.closedStatus != null; + executor.waitAndDrainWithTimeout(waitForever, end, predicate, this); + Status savedClosedStatus = closedStatus; + if (savedClosedStatus == null) { + call.sendMessage(request); + return true; + } else if (savedClosedStatus.isOk()) { + return false; + } else { + // Propagate any errors returned from the server + throw savedClosedStatus.asException(); + } + } + + void sendSingleRequest(ReqT request) { + call.sendMessage(request); + } + + /** + * Cancel stream and stop any further writes. Note that some reads that are in flight may still + * happen after the cancel. + * + * @param message if not {@code null}, will appear as the description of the CANCELLED status + * @param cause if not {@code null}, will appear as the cause of the CANCELLED status + */ + public void cancel(String message, Throwable cause) { + writeClosed = true; + call.cancel(message, cause); + } + + /** + * Indicate that no more writes will be done and the stream will be closed from the client side. + * + * @see ClientCall#halfClose() + */ + public void halfClose() { + if (writeClosed) { + throw new IllegalStateException( + "halfClose cannot be called after already half closed or cancelled"); + } + + writeClosed = true; + call.halfClose(); + } + + /** + * Status that server sent when closing channel from its side. + * + * @return null if stream not closed by server, otherwise Status sent by server + */ + @VisibleForTesting + Status getClosedStatus() { + drainQuietly(); + return closedStatus; + } + + /** + * Check for whether some action is ready. + * + * @return True if legal to write and writeOrRead can run without blocking + */ + @VisibleForTesting + boolean isEitherReadOrWriteReady() { + return (isWriteLegal() && isWriteReady()) || isReadReady(); + } + + /** + * Check whether there are any values waiting to be read. + * + * @return true if read will not block + */ + @VisibleForTesting + boolean isReadReady() { + drainQuietly(); + + return !buffer.isEmpty(); + } + + /** + * Check that write hasn't been marked complete and stream is ready to receive a write (so will + * not block). + * + * @return true if legal to write and write will not block + */ + @VisibleForTesting + boolean isWriteReady() { + drainQuietly(); + + return isWriteLegal() && call.isReady(); + } + + /** + * Check whether we'll ever be able to do writes or should terminate. + * @return True if writes haven't been closed and the server hasn't closed the stream + */ + private boolean isWriteLegal() { + return !writeClosed && closedStatus == null; + } + + ClientCall.Listener getListener() { + return new QueuingListener(); + } + + private void drainQuietly() { + try { + executor.drain(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + + private final class QueuingListener extends ClientCall.Listener { + @Override + public void onMessage(RespT value) { + Preconditions.checkState(closedStatus == null, "ClientCall already closed"); + buffer.add(value); + } + + @Override + public void onClose(Status status, Metadata trailers) { + Preconditions.checkState(closedStatus == null, "ClientCall already closed"); + closedStatus = status; + } + } + +} diff --git a/stub/src/main/java/io/grpc/stub/ClientCalls.java b/stub/src/main/java/io/grpc/stub/ClientCalls.java index 13fb00d3b3e..f307c806489 100644 --- a/stub/src/main/java/io/grpc/stub/ClientCalls.java +++ b/stub/src/main/java/io/grpc/stub/ClientCalls.java @@ -22,12 +22,14 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; import com.google.common.base.Strings; import com.google.common.util.concurrent.AbstractFuture; import com.google.common.util.concurrent.ListenableFuture; import io.grpc.CallOptions; import io.grpc.Channel; import io.grpc.ClientCall; +import io.grpc.ExperimentalApi; import io.grpc.Metadata; import io.grpc.MethodDescriptor; import io.grpc.Status; @@ -42,9 +44,14 @@ import java.util.concurrent.Executor; import java.util.concurrent.Future; import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.LockSupport; +import java.util.concurrent.locks.ReentrantLock; import java.util.logging.Level; import java.util.logging.Logger; +import javax.annotation.Nonnull; import javax.annotation.Nullable; /** @@ -184,7 +191,6 @@ public static RespT blockingUnaryCall( * * @return an iterator over the response stream. */ - // TODO(louiscryan): Not clear if we want to use this idiom for 'simple' stubs. public static Iterator blockingServerStreamingCall( ClientCall call, ReqT req) { BlockingResponseStream result = new BlockingResponseStream<>(call); @@ -194,11 +200,12 @@ public static Iterator blockingServerStreamingCall( /** * Executes a server-streaming call returning a blocking {@link Iterator} over the - * response stream. The {@code call} should not be already started. After calling this method, - * {@code call} should no longer be used. + * response stream. * *

The returned iterator may throw {@link StatusRuntimeException} on error. * + *

Warning: the iterator can result in leaks if not completely consumed. + * * @return an iterator over the response stream. */ public static Iterator blockingServerStreamingCall( @@ -211,6 +218,82 @@ public static Iterator blockingServerStreamingCall( return result; } + /** + * Initiates a client streaming call over the specified channel. It returns an + * object which can be used in a blocking manner to retrieve responses.. + * + *

The methods {@link BlockingClientCall#hasNext()} and {@link + * BlockingClientCall#cancel(String, Throwable)} can be used for more extensive control. + * + * @return A {@link BlockingClientCall} that has had the request sent and halfClose called + */ + @ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public static BlockingClientCall blockingV2ServerStreamingCall( + Channel channel, MethodDescriptor method, CallOptions callOptions, ReqT req) { + BlockingClientCall call = + blockingBidiStreamingCall(channel, method, callOptions); + + call.sendSingleRequest(req); + call.halfClose(); + return call; + } + + /** + * Initiates a server streaming call and sends the specified request to the server. It returns an + * object which can be used in a blocking manner to retrieve values from the server. After the + * last value has been read, the next read call will return null. + * + *

Call {@link BlockingClientCall#read()} for + * retrieving values. A {@code null} will be returned after the server has closed the stream. + * + *

The methods {@link BlockingClientCall#hasNext()} and {@link + * BlockingClientCall#cancel(String, Throwable)} can be used for more extensive control. + * + *


Example usage: + *

 {@code  while ((response = call.read()) != null) { ... } } 
+ * or + *
 {@code
+   *   while (call.hasNext()) {
+   *     response = call.read();
+   *     ...
+   *   }
+   * } 
+ * + *

Note that this paradigm is different from the original + * {@link #blockingServerStreamingCall(Channel, MethodDescriptor, CallOptions, Object)} + * which returns an iterator, which would leave the stream open if not completely consumed. + * + * @return A {@link BlockingClientCall} which can be used by the client to write and receive + * messages over the grpc channel. + */ + @ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public static BlockingClientCall blockingClientStreamingCall( + Channel channel, MethodDescriptor method, CallOptions callOptions) { + return blockingBidiStreamingCall(channel, method, callOptions); + } + + /** + * Initiate a bidirectional-streaming {@link ClientCall} and returning a stream object + * ({@link BlockingClientCall}) which can be used by the client to send and receive messages over + * the grpc channel. + * + * @return an object representing the call which can be used to read, write and terminate it. + */ + @ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public static BlockingClientCall blockingBidiStreamingCall( + Channel channel, MethodDescriptor method, CallOptions callOptions) { + ThreadSafeThreadlessExecutor executor = new ThreadSafeThreadlessExecutor(); + ClientCall call = channel.newCall(method, callOptions.withExecutor(executor)); + + BlockingClientCall blockingClientCall = new BlockingClientCall<>(call, executor); + + // Get the call started + call.start(blockingClientCall.getListener(), new Metadata()); + call.request(1); + + return blockingClientCall; + } + /** * Executes a unary call and returns a {@link ListenableFuture} to the response. The * {@code call} should not be already started. After calling this method, {@code call} should no @@ -414,7 +497,7 @@ public void disableAutoRequestWithInitial(int request) { public void request(int count) { if (!streamingResponse && count == 1) { // Initially ask for two responses from flow-control so that if a misbehaving server - // sends more than one responses, we can catch it and fail it in the listener. + // sends more than one response, we can catch it and fail it in the listener. call.request(2); } else { call.request(count); @@ -637,7 +720,7 @@ public boolean hasNext() { public T next() { // Eagerly call request(1) so it can be processing the next message while we wait for the // current one, which reduces latency for the next message. With MigratingThreadDeframer and - // if the data has already been recieved, every other message can be delivered instantly. This + // if the data has already been received, every other message can be delivered instantly. This // can be run after hasNext(), but just would be slower. if (!(last instanceof StatusRuntimeException) && last != this) { call.request(1); @@ -726,6 +809,12 @@ public void waitAndDrain() throws InterruptedException { } while ((runnable = poll()) != null); } + private static void throwIfInterrupted() throws InterruptedException { + if (Thread.interrupted()) { + throw new InterruptedException(); + } + } + /** * Called after final call to {@link #waitAndDrain()}, from same thread. */ @@ -745,12 +834,6 @@ private static void runQuietly(Runnable runnable) { } } - private static void throwIfInterrupted() throws InterruptedException { - if (Thread.interrupted()) { - throw new InterruptedException(); - } - } - @Override public void execute(Runnable runnable) { add(runnable); @@ -763,6 +846,131 @@ public void execute(Runnable runnable) { } } + @SuppressWarnings("serial") + static final class ThreadSafeThreadlessExecutor extends ConcurrentLinkedQueue + implements Executor { + private static final Logger log = + Logger.getLogger(ThreadSafeThreadlessExecutor.class.getName()); + + private final Lock waiterLock = new ReentrantLock(); + private final Condition waiterCondition = waiterLock.newCondition(); + + // Non private to avoid synthetic class + ThreadSafeThreadlessExecutor() {} + + /** + * Waits until there is a Runnable, then executes it and all queued Runnables after it. + */ + public void waitAndDrain(Predicate predicate, T testTarget) throws InterruptedException { + try { + waitAndDrainWithTimeout(true, 0, predicate, testTarget); + } catch (TimeoutException e) { + throw new AssertionError(e); // Should never happen + } + } + + /** + * Waits for up to specified nanoseconds until there is a Runnable, then executes it and all + * queued Runnables after it. + * + *

his should always be called in a loop that checks whether the reason we are waiting has + * been satisfied.

T + * + * @param waitForever ignore the rest of the arguments and wait until there is a task to run + * @param end System.nanoTime() to stop waiting if haven't been woken up yet + * @param predicate non-null condition to test for skipping wake or waking up threads + * @param testTarget object to pass to predicate + */ + public void waitAndDrainWithTimeout(boolean waitForever, long end, + @Nonnull Predicate predicate, T testTarget) + throws InterruptedException, TimeoutException { + throwIfInterrupted(); + Runnable runnable; + + while (!predicate.apply(testTarget)) { + waiterLock.lock(); + try { + while ((runnable = poll()) == null) { + if (predicate.apply(testTarget)) { + return; // The condition for which we were waiting is now satisfied + } + + if (waitForever) { + waiterCondition.await(); + } else { + long waitNanos = end - System.nanoTime(); + if (waitNanos <= 0) { + throw new TimeoutException(); // Deadline is expired + } + waiterCondition.awaitNanos(waitNanos); + } + } + } finally { + waiterLock.unlock(); + } + + do { + runQuietly(runnable); + } while ((runnable = poll()) != null); + // Wake everything up now that we've done something and they can check in their outer loop + // if they can continue or need to wait again. + signallAll(); + } + } + + /** + * Executes all queued Runnables and if there were any wakes up any waiting threads. + */ + public void drain() throws InterruptedException { + throwIfInterrupted(); + Runnable runnable; + boolean didWork = false; + + while ((runnable = poll()) != null) { + runQuietly(runnable); + didWork = true; + } + + if (didWork) { + signallAll(); + } + } + + private void signallAll() { + waiterLock.lock(); + try { + waiterCondition.signalAll(); + } finally { + waiterLock.unlock(); + } + } + + private static void runQuietly(Runnable runnable) { + try { + runnable.run(); + } catch (Throwable t) { + log.log(Level.WARNING, "Runnable threw exception", t); + } + } + + private static void throwIfInterrupted() throws InterruptedException { + if (Thread.interrupted()) { + throw new InterruptedException(); + } + } + + @Override + public void execute(Runnable runnable) { + waiterLock.lock(); + try { + add(runnable); + waiterCondition.signalAll(); // If anything is waiting let it wake up and process this task + } finally { + waiterLock.unlock(); + } + } + } + enum StubType { BLOCKING, FUTURE, ASYNC } diff --git a/stub/src/test/java/io/grpc/stub/AbstractStubTest.java b/stub/src/test/java/io/grpc/stub/AbstractStubTest.java index a167c735160..352a2fb7fe2 100644 --- a/stub/src/test/java/io/grpc/stub/AbstractStubTest.java +++ b/stub/src/test/java/io/grpc/stub/AbstractStubTest.java @@ -28,6 +28,7 @@ import io.grpc.stub.AbstractStub.StubFactory; import io.grpc.stub.AbstractStubTest.NoopStub; import java.time.Duration; +import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -54,6 +55,7 @@ public NoopStub newStub(Channel channel, CallOptions callOptions) { } @Test + @IgnoreJRERequirement public void testDuration() { NoopStub stub = NoopStub.newStub(new StubFactory() { @Override diff --git a/stub/src/test/java/io/grpc/stub/BlockingClientCallTest.java b/stub/src/test/java/io/grpc/stub/BlockingClientCallTest.java new file mode 100644 index 00000000000..112b092eaed --- /dev/null +++ b/stub/src/test/java/io/grpc/stub/BlockingClientCallTest.java @@ -0,0 +1,520 @@ +/* + * Copyright 2023 The gRPC Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc.stub; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import io.grpc.CallOptions; +import io.grpc.ManagedChannel; +import io.grpc.MethodDescriptor; +import io.grpc.MethodDescriptor.MethodType; +import io.grpc.Server; +import io.grpc.ServerServiceDefinition; +import io.grpc.ServiceDescriptor; +import io.grpc.Status; +import io.grpc.Status.Code; +import io.grpc.StatusException; +import io.grpc.inprocess.InProcessChannelBuilder; +import io.grpc.inprocess.InProcessServerBuilder; +import io.grpc.stub.ServerCalls.BidiStreamingMethod; +import io.grpc.stub.ServerCallsTest.IntegerMarshaller; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.logging.Logger; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class BlockingClientCallTest { + private static final Logger logger = Logger.getLogger(BlockingClientCallTest.class.getName()); + + public static final int DELAY_MILLIS = 2000; + public static final long DELAY_NANOS = TimeUnit.MILLISECONDS.toNanos(DELAY_MILLIS); + private static final MethodDescriptor BIDI_STREAMING_METHOD = + MethodDescriptor.newBuilder() + .setType(MethodType.BIDI_STREAMING) + .setFullMethodName("some/method") + .setRequestMarshaller(new IntegerMarshaller()) + .setResponseMarshaller(new IntegerMarshaller()) + .build(); + + private Server server; + + private ManagedChannel channel; + + private IntegerTestMethod testMethod; + private BlockingClientCall biDiStream; + + @Before + public void setUp() throws Exception { + testMethod = new IntegerTestMethod(); + + ServerServiceDefinition service = ServerServiceDefinition.builder( + new ServiceDescriptor("some", BIDI_STREAMING_METHOD)) + .addMethod(BIDI_STREAMING_METHOD, ServerCalls.asyncBidiStreamingCall(testMethod)) + .build(); + long tag = System.nanoTime(); + + server = InProcessServerBuilder.forName("go-with-the-flow" + tag).directExecutor() + .addService(service).build().start(); + + channel = InProcessChannelBuilder.forName("go-with-the-flow" + tag).directExecutor().build(); + } + + @After + public void tearDown() { + if (server != null) { + server.shutdownNow(); + } + if (channel != null) { + channel.shutdownNow(); + } + if (biDiStream != null) { + biDiStream.cancel("In teardown", null); + } + } + + @Test + public void sanityTest() throws Exception { + Integer req = 2; + biDiStream = ClientCalls.blockingBidiStreamingCall(channel, BIDI_STREAMING_METHOD, + CallOptions.DEFAULT); + + // verify activity ready + assertTrue(biDiStream.isEitherReadOrWriteReady()); + assertTrue(biDiStream.isWriteReady()); + + // Have server send a value + testMethod.sendValueToClient(10); + + // Do a writeOrRead + biDiStream.write(req, 3, TimeUnit.SECONDS); + assertEquals(Integer.valueOf(10), biDiStream.read(DELAY_MILLIS, TimeUnit.MILLISECONDS)); + + // mark complete + biDiStream.halfClose(); + assertNull(biDiStream.read(2, TimeUnit.SECONDS)); + + // verify activity !ready and !writeable + assertFalse(biDiStream.isEitherReadOrWriteReady()); + assertFalse(biDiStream.isWriteReady()); + + assertEquals(Code.OK, biDiStream.getClosedStatus().getCode()); + } + + @Test + public void testReadSuccess_withoutBlocking() throws Exception { + biDiStream = ClientCalls.blockingBidiStreamingCall(channel, BIDI_STREAMING_METHOD, + CallOptions.DEFAULT); + + // Have server push a value + testMethod.sendValueToClient(11); + + long start = System.nanoTime(); + Integer value = biDiStream.read(100, TimeUnit.SECONDS); + assertNotNull(value); + long timeTaken = System.nanoTime() - start; + assertThat(timeTaken).isLessThan(TimeUnit.MILLISECONDS.toNanos(100)); + } + + @Test + public void testReadSuccess_withBlocking() throws Exception { + biDiStream = ClientCalls.blockingBidiStreamingCall(channel, BIDI_STREAMING_METHOD, + CallOptions.DEFAULT); + + try { + biDiStream.read(1, TimeUnit.SECONDS); + fail("Expected timeout"); + } catch (TimeoutException t) { + // ignore + } + + long start = System.nanoTime(); + delayedAddValue(DELAY_MILLIS, 12); + assertNotNull(biDiStream.read(DELAY_MILLIS * 2, TimeUnit.MILLISECONDS)); + long timeTaken = System.nanoTime() - start; + assertThat(timeTaken).isGreaterThan(DELAY_NANOS); + assertThat(timeTaken).isLessThan(DELAY_NANOS * 2); + + start = System.nanoTime(); + Integer[] values = {13, 14, 15, 16}; + delayedAddValue(DELAY_MILLIS, values); + for (Integer value : values) { + Integer readValue = biDiStream.read(DELAY_MILLIS * 2, TimeUnit.MILLISECONDS); + assertEquals(value, readValue); + } + timeTaken = System.nanoTime() - start; + assertThat(timeTaken).isLessThan(DELAY_NANOS * 2); + assertThat(timeTaken).isAtLeast(DELAY_NANOS); + + start = System.nanoTime(); + delayedVoidMethod(100, testMethod::halfClose); + assertNull(biDiStream.read(DELAY_MILLIS * 2, TimeUnit.MILLISECONDS)); + timeTaken = System.nanoTime() - start; + assertThat(timeTaken).isLessThan(DELAY_NANOS); + } + + @Test + public void testCancel() throws Exception { + testMethod.disableAutoRequest(); + biDiStream = ClientCalls.blockingBidiStreamingCall(channel, BIDI_STREAMING_METHOD, + CallOptions.DEFAULT); + + // read terminated + long start = System.currentTimeMillis(); + delayedCancel(biDiStream, "cancel read"); + try { + assertNull(biDiStream.read(2 * DELAY_MILLIS, TimeUnit.MILLISECONDS)); + fail("No exception thrown by read after cancel"); + } catch (StatusException e) { + assertEquals(Status.CANCELLED.getCode(), e.getStatus().getCode()); + assertThat(System.currentTimeMillis() - start).isLessThan(2 * DELAY_MILLIS); + } + + // write terminated + biDiStream = ClientCalls.blockingBidiStreamingCall(channel, BIDI_STREAMING_METHOD, + CallOptions.DEFAULT); + start = System.currentTimeMillis(); + delayedCancel(biDiStream, "cancel write"); + + // Write interrupted by cancel + try { + assertFalse(biDiStream.write(30)); // this is interrupted by cancel + fail("No exception thrown when write was interrupted by cancel"); + } catch (StatusException e) { + assertEquals(Status.CANCELLED.getCode(), e.getStatus().getCode()); + } + + // Write after cancel + try { + start = System.currentTimeMillis(); + biDiStream.write(30); + fail("No exception doing write after cancel"); + } catch (IllegalStateException e) { + assertThat(System.currentTimeMillis() - start).isLessThan(200); + assertThat(e.getMessage()).contains("cancel"); + } + + // new read after cancel immediately throws an exception + try { + start = System.currentTimeMillis(); + assertNull(biDiStream.read(2, TimeUnit.SECONDS)); + } catch (StatusException e) { + assertEquals(Status.CANCELLED.getCode(), e.getStatus().getCode()); + assertThat(System.currentTimeMillis() - start).isLessThan(200); + } + + } + + @Test + public void testIsActivityReady() throws Exception { + biDiStream = ClientCalls.blockingBidiStreamingCall(channel, BIDI_STREAMING_METHOD, + CallOptions.DEFAULT); + + // write only ready + assertTrue(biDiStream.isEitherReadOrWriteReady()); + assertTrue(biDiStream.isWriteReady()); + assertFalse(biDiStream.isReadReady()); + + // both ready + testMethod.sendValueToClient(40); + assertTrue(biDiStream.isEitherReadOrWriteReady()); + assertTrue(biDiStream.isReadReady()); + assertTrue(biDiStream.isWriteReady()); + + // read only ready + biDiStream.halfClose(); + assertTrue(biDiStream.isEitherReadOrWriteReady()); + assertTrue(biDiStream.isReadReady()); + assertFalse(biDiStream.isWriteReady()); + + // Neither ready + assertNotNull(biDiStream.read(1, TimeUnit.MILLISECONDS)); + assertFalse(biDiStream.isEitherReadOrWriteReady()); + assertFalse(biDiStream.isReadReady()); + assertFalse(biDiStream.isWriteReady()); + } + + @Test + public void testWriteSuccess_withBlocking() throws Exception { + testMethod.disableAutoRequest(); + biDiStream = ClientCalls.blockingBidiStreamingCall(channel, BIDI_STREAMING_METHOD, + CallOptions.DEFAULT); + + assertFalse(biDiStream.isWriteReady()); + delayedWriteEnable(500); + assertTrue(biDiStream.write(40)); + + delayedWriteEnable(500); + assertTrue(biDiStream.write(41, 0, TimeUnit.NANOSECONDS)); + } + + + @Test + public void testReadNonblocking_whenWriteBlocked() throws Exception { + testMethod.disableAutoRequest(); + biDiStream = ClientCalls.blockingBidiStreamingCall(channel, BIDI_STREAMING_METHOD, + CallOptions.DEFAULT); + + // One value waiting + testMethod.sendValueToClient(50); + long start = System.currentTimeMillis(); + assertEquals(Integer.valueOf(50), biDiStream.read()); + assertThat(System.currentTimeMillis() - start).isLessThan(DELAY_MILLIS); + + // Two values waiting + start = System.currentTimeMillis(); + testMethod.sendValuesToClient(51, 52); + assertEquals(Integer.valueOf(51), biDiStream.read()); + assertEquals(Integer.valueOf(52), biDiStream.read()); + assertThat(System.currentTimeMillis() - start).isLessThan(DELAY_MILLIS); + } + + @Test + public void testReadsAndWritesInterleaved_withBlocking() throws Exception { + biDiStream = ClientCalls.blockingBidiStreamingCall(channel, BIDI_STREAMING_METHOD, + CallOptions.DEFAULT); + + Integer[] valuesOut = {1001, 10022, 1003}; + Integer[] valuesIn = new Integer[valuesOut.length]; + delayedAddValue(300, valuesOut); + int iteration = 0; + for (int i = 0; i < valuesOut.length && iteration++ < (20 + valuesOut.length); ) { + try { + if ((valuesIn[i] = biDiStream.read(50, TimeUnit.MILLISECONDS)) != null) { + i++; + } + } catch (TimeoutException e) { + logger.info("Read timed out for " + i); + } + } + assertArrayEquals(valuesOut, valuesIn); + } + + @Test + public void testReadsAndWritesInterleaved_BlockingWrites() throws Exception { + testMethod.disableAutoRequest(); + biDiStream = ClientCalls.blockingBidiStreamingCall(channel, BIDI_STREAMING_METHOD, + CallOptions.DEFAULT); + + testMethod.sendValuesToClient(10, 11, 12); + delayedWriteEnable(500); + long start = System.currentTimeMillis(); + boolean done = false; + int count = 0; + while (!done) { + count++; + if (!biDiStream.isWriteReady() && biDiStream.isReadReady()) { + biDiStream.read(100, TimeUnit.MILLISECONDS); + } else { + done = biDiStream.write(100, 1, TimeUnit.SECONDS); + } + } + assertEquals(4, count); + assertThat(System.currentTimeMillis() - start).isLessThan(700); + + testMethod.sendValuesToClient(20, 21, 22); + delayedWriteEnable(100); + while (!biDiStream.isWriteReady()) { + Thread.sleep(20); + } + + assertTrue(biDiStream.write(1000, 2 * DELAY_MILLIS, TimeUnit.MILLISECONDS)); + + assertEquals(Integer.valueOf(20), biDiStream.read(200, TimeUnit.MILLISECONDS)); + assertEquals(Integer.valueOf(21), biDiStream.read(200, TimeUnit.MILLISECONDS)); + assertEquals(Integer.valueOf(22), biDiStream.read(200, TimeUnit.MILLISECONDS)); + try { + Integer value = biDiStream.read(200, TimeUnit.MILLISECONDS); + fail("Unexpected read success instead of timeout. Value was: " + value); + } catch (TimeoutException ignore) { + // ignore since expected + } + } + + @Test + public void testWriteCompleted() throws Exception { + testMethod.disableAutoRequest(); + biDiStream = ClientCalls.blockingBidiStreamingCall(channel, BIDI_STREAMING_METHOD, + CallOptions.DEFAULT); + + // Verify pending write released + long start = System.currentTimeMillis(); + delayedVoidMethod(DELAY_MILLIS, biDiStream::halfClose); + assertFalse(biDiStream.write(1)); // should block until writeComplete is triggered + long end = System.currentTimeMillis(); + assertThat(end - start).isAtLeast(DELAY_MILLIS); + + // verify new writes throw an illegalStateException + try { + assertFalse(biDiStream.write(2)); + fail("write did not throw an exception when called after halfClose"); + } catch (IllegalStateException e) { + assertThat(e.getMessage()).containsMatch("after.*halfClose.*cancel"); + } + + // verify pending write with timeout released + biDiStream = ClientCalls.blockingBidiStreamingCall(channel, BIDI_STREAMING_METHOD, + CallOptions.DEFAULT); + delayedVoidMethod(DELAY_MILLIS, biDiStream::halfClose); + assertFalse(biDiStream.write(3, 2 * DELAY_MILLIS, TimeUnit.MILLISECONDS)); + } + + @Test + public void testClose_withException() throws Exception { + biDiStream = ClientCalls.blockingBidiStreamingCall(channel, BIDI_STREAMING_METHOD, + CallOptions.DEFAULT); + + String descr = "too many small numbers"; + testMethod.sendError( + Status.FAILED_PRECONDITION.withDescription(descr).asRuntimeException()); + Status closedStatus = biDiStream.getClosedStatus(); + assertEquals(Code.FAILED_PRECONDITION, closedStatus.getCode()); + assertEquals(descr, closedStatus.getDescription()); + try { + assertFalse(biDiStream.write(1)); + } catch (StatusException e) { + assertThat(e.getMessage()).startsWith("FAILED_PRECONDITION"); + } + } + + private void delayedAddValue(int delayMillis, Integer... values) { + new Thread("delayedAddValue " + values.length) { + @Override + public void run() { + try { + Thread.sleep(delayMillis); + for (Integer cur : values) { + testMethod.sendValueToClient(cur); + } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + }.start(); + } + + public interface Thunk { void apply(); } // supports passing void method w/out args + + private void delayedVoidMethod(int delayMillis, Thunk method) { + new Thread("delayedHalfClose") { + @Override + public void run() { + try { + Thread.sleep(delayMillis); + method.apply(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + }.start(); + } + + private void delayedWriteEnable(int delayMillis) { + delayedVoidMethod(delayMillis, testMethod::readValueFromClient); + } + + private void delayedCancel(BlockingClientCall biDiStream, String message) { + new Thread("delayedCancel") { + @Override + public void run() { + try { + Thread.sleep(BlockingClientCallTest.DELAY_MILLIS); + biDiStream.cancel(message, new RuntimeException("Test requested close")); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + }.start(); + } + + private static class IntegerTestMethod implements BidiStreamingMethod { + boolean autoRequest = true; + + void disableAutoRequest() { + assertNull("Can't disable auto request after invoke has been called", serverCallObserver); + autoRequest = false; + } + + ServerCallStreamObserver serverCallObserver; + + @Override + public StreamObserver invoke(StreamObserver responseObserver) { + serverCallObserver = (ServerCallStreamObserver) responseObserver; + if (!autoRequest) { + serverCallObserver.disableAutoRequest(); + } + + return new StreamObserver() { + @Override + public void onNext(Integer value) { + if (!autoRequest) { + serverCallObserver.request(1); + } + + // For testing ReqResp actions + if (value > 1000) { + serverCallObserver.onNext(value); + } + } + + @Override + public void onError(Throwable t) { + // no-op + } + + @Override + public void onCompleted() { + serverCallObserver.onCompleted(); + } + }; + } + + void readValueFromClient() { + serverCallObserver.request(1); + } + + void sendValueToClient(int value) { + serverCallObserver.onNext(value); + } + + private void sendValuesToClient(int ...values) { + for (int cur : values) { + sendValueToClient(cur); + } + } + + void halfClose() { + serverCallObserver.onCompleted(); + } + + void sendError(Throwable t) { + serverCallObserver.onError(t); + } + } + +} diff --git a/stub/src/test/java/io/grpc/stub/ClientCallsTest.java b/stub/src/test/java/io/grpc/stub/ClientCallsTest.java index f3d101b862a..b711b2a23b5 100644 --- a/stub/src/test/java/io/grpc/stub/ClientCallsTest.java +++ b/stub/src/test/java/io/grpc/stub/ClientCallsTest.java @@ -971,8 +971,8 @@ public ClientCall interceptCall( } @Override public void halfClose() { - Thread.currentThread().interrupt(); super.halfClose(); + Thread.currentThread().interrupt(); } }; } diff --git a/testing-proto/build.gradle b/testing-proto/build.gradle index e6afce468f0..a34392b26d2 100644 --- a/testing-proto/build.gradle +++ b/testing-proto/build.gradle @@ -20,7 +20,11 @@ dependencies { compileOnly libraries.javax.annotation testImplementation libraries.truth testRuntimeOnly libraries.javax.annotation - signature libraries.signature.java + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } } configureProtoCompilation() diff --git a/testing-proto/src/generated/main/grpc/io/grpc/testing/protobuf/SimpleServiceGrpc.java b/testing-proto/src/generated/main/grpc/io/grpc/testing/protobuf/SimpleServiceGrpc.java index 8c58f2c5a2c..8b33691535d 100644 --- a/testing-proto/src/generated/main/grpc/io/grpc/testing/protobuf/SimpleServiceGrpc.java +++ b/testing-proto/src/generated/main/grpc/io/grpc/testing/protobuf/SimpleServiceGrpc.java @@ -156,6 +156,21 @@ public SimpleServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions ca return SimpleServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static SimpleServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public SimpleServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new SimpleServiceBlockingV2Stub(channel, callOptions); + } + }; + return SimpleServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -318,6 +333,72 @@ public io.grpc.stub.StreamObserver bidiS * A simple service for test. * */ + public static final class SimpleServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private SimpleServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected SimpleServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new SimpleServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * Simple unary RPC.
+     * 
+ */ + public io.grpc.testing.protobuf.SimpleResponse unaryRpc(io.grpc.testing.protobuf.SimpleRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getUnaryRpcMethod(), getCallOptions(), request); + } + + /** + *
+     * Simple client-to-server streaming RPC.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + clientStreamingRpc() { + return io.grpc.stub.ClientCalls.blockingClientStreamingCall( + getChannel(), getClientStreamingRpcMethod(), getCallOptions()); + } + + /** + *
+     * Simple server-to-client streaming RPC.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + serverStreamingRpc(io.grpc.testing.protobuf.SimpleRequest request) { + return io.grpc.stub.ClientCalls.blockingV2ServerStreamingCall( + getChannel(), getServerStreamingRpcMethod(), getCallOptions(), request); + } + + /** + *
+     * Simple bidirectional streaming RPC.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + bidiStreamingRpc() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getBidiStreamingRpcMethod(), getCallOptions()); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service SimpleService. + *
+   * A simple service for test.
+   * 
+ */ public static final class SimpleServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private SimpleServiceBlockingStub( diff --git a/testing/build.gradle b/testing/build.gradle index cc83b7ad620..b92e39279c6 100644 --- a/testing/build.gradle +++ b/testing/build.gradle @@ -24,8 +24,16 @@ dependencies { testImplementation project(':grpc-testing-proto'), testFixtures(project(':grpc-core')) - signature libraries.signature.java - signature libraries.signature.android + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } + signature (libraries.signature.android) { + artifact { + extension = "signature" + } + } } tasks.named("javadoc").configure { exclude 'io/grpc/internal/**' } diff --git a/util/build.gradle b/util/build.gradle index 932ca66883e..6fbd6925c00 100644 --- a/util/build.gradle +++ b/util/build.gradle @@ -35,8 +35,16 @@ dependencies { project(':grpc-testing') jmh project(':grpc-testing') - signature libraries.signature.java - signature libraries.signature.android + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } + signature (libraries.signature.android) { + artifact { + extension = "signature" + } + } } animalsniffer { diff --git a/util/src/main/java/io/grpc/util/AdvancedTlsX509TrustManager.java b/util/src/main/java/io/grpc/util/AdvancedTlsX509TrustManager.java index 088f4caa000..b4b9b25d1de 100644 --- a/util/src/main/java/io/grpc/util/AdvancedTlsX509TrustManager.java +++ b/util/src/main/java/io/grpc/util/AdvancedTlsX509TrustManager.java @@ -265,7 +265,7 @@ public Closeable updateTrustCredentials(File trustCertFile, long period, TimeUni } final ScheduledFuture future = checkNotNull(executor, "executor").scheduleWithFixedDelay( - new LoadFilePathExecution(trustCertFile), period, period, unit); + new LoadFilePathExecution(trustCertFile, updatedTime), period, period, unit); return () -> future.cancel(false); } @@ -312,9 +312,9 @@ private class LoadFilePathExecution implements Runnable { File file; long currentTime; - public LoadFilePathExecution(File file) { + public LoadFilePathExecution(File file, long currentTime) { this.file = file; - this.currentTime = 0; + this.currentTime = currentTime; } @Override diff --git a/util/src/main/java/io/grpc/util/OutlierDetectionLoadBalancer.java b/util/src/main/java/io/grpc/util/OutlierDetectionLoadBalancer.java index 1f0290e76d7..928592e5534 100644 --- a/util/src/main/java/io/grpc/util/OutlierDetectionLoadBalancer.java +++ b/util/src/main/java/io/grpc/util/OutlierDetectionLoadBalancer.java @@ -685,7 +685,11 @@ void updateTrackerConfigs(OutlierDetectionLoadBalancerConfig config) { /** Adds a new tracker for every given address. */ void putNewTrackers(OutlierDetectionLoadBalancerConfig config, Set> endpoints) { - endpoints.forEach(e -> trackerMap.putIfAbsent(e, new EndpointTracker(config))); + for (Set endpoint : endpoints) { + if (!trackerMap.containsKey(endpoint)) { + trackerMap.put(endpoint, new EndpointTracker(config)); + } + } } /** Resets the call counters for all the trackers in the map. */ diff --git a/util/src/test/java/io/grpc/util/AdvancedTlsX509TrustManagerTest.java b/util/src/test/java/io/grpc/util/AdvancedTlsX509TrustManagerTest.java index 36ef75abeaa..228dbf5ea5b 100644 --- a/util/src/test/java/io/grpc/util/AdvancedTlsX509TrustManagerTest.java +++ b/util/src/test/java/io/grpc/util/AdvancedTlsX509TrustManagerTest.java @@ -24,6 +24,7 @@ import static org.mockito.Mockito.when; import com.google.common.collect.Iterables; +import com.google.common.io.Files; import io.grpc.internal.FakeClock; import io.grpc.internal.testing.TestUtils; import io.grpc.testing.TlsTesting; @@ -44,6 +45,7 @@ import java.util.logging.LogRecord; import java.util.logging.Logger; import javax.net.ssl.SSLSocket; +import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -51,25 +53,33 @@ /** Unit tests for {@link AdvancedTlsX509TrustManager}. */ @RunWith(JUnit4.class) +@IgnoreJRERequirement public class AdvancedTlsX509TrustManagerTest { private static final String CA_PEM_FILE = "ca.pem"; private static final String SERVER_0_PEM_FILE = "server0.pem"; + private static final String SERVER_1_PEM_FILE = "server1.pem"; private File caCertFile; private File serverCert0File; + private File serverCert1File; private X509Certificate[] caCert; private X509Certificate[] serverCert0; + private X509Certificate[] serverCert1; + private FakeClock fakeClock; private ScheduledExecutorService executor; @Before public void setUp() throws IOException, GeneralSecurityException { - executor = new FakeClock().getScheduledExecutorService(); + fakeClock = new FakeClock(); + executor = fakeClock.getScheduledExecutorService(); caCertFile = TestUtils.loadCert(CA_PEM_FILE); caCert = CertificateUtils.getX509Certificates(TlsTesting.loadCert(CA_PEM_FILE)); serverCert0File = TestUtils.loadCert(SERVER_0_PEM_FILE); serverCert0 = CertificateUtils.getX509Certificates(TlsTesting.loadCert(SERVER_0_PEM_FILE)); + serverCert1File = TestUtils.loadCert(SERVER_1_PEM_FILE); + serverCert1 = CertificateUtils.getX509Certificates(TlsTesting.loadCert(SERVER_1_PEM_FILE)); } @Test @@ -145,6 +155,39 @@ public void clientTrustedWithSocketTest() throws Exception { assertEquals("No handshake session", ce.getMessage()); } + @Test + public void updateTrustCredentials_rotate() throws GeneralSecurityException, IOException { + AdvancedTlsX509TrustManager trustManager = AdvancedTlsX509TrustManager.newBuilder().build(); + trustManager.updateTrustCredentials(serverCert0File); + assertArrayEquals(serverCert0, trustManager.getAcceptedIssuers()); + + trustManager.updateTrustCredentials(serverCert0File, 1, TimeUnit.MINUTES, + executor); + assertArrayEquals(serverCert0, trustManager.getAcceptedIssuers()); + + fakeClock.forwardTime(1, TimeUnit.MINUTES); + assertArrayEquals(serverCert0, trustManager.getAcceptedIssuers()); + + serverCert0File.setLastModified(serverCert0File.lastModified() - 2000); + + fakeClock.forwardTime(1, TimeUnit.MINUTES); + assertArrayEquals(serverCert0, trustManager.getAcceptedIssuers()); + + long beforeModify = serverCert0File.lastModified(); + Files.copy(serverCert1File, serverCert0File); + serverCert0File.setLastModified(beforeModify); + + // although file content changed, file modification time is not changed + fakeClock.forwardTime(1, TimeUnit.MINUTES); + assertArrayEquals(serverCert0, trustManager.getAcceptedIssuers()); + + serverCert0File.setLastModified(beforeModify + 2000); + + // file modification time changed + fakeClock.forwardTime(1, TimeUnit.MINUTES); + assertArrayEquals(serverCert1, trustManager.getAcceptedIssuers()); + } + private static class TestHandler extends Handler { private final List records = new ArrayList<>(); diff --git a/xds/build.gradle b/xds/build.gradle index e09b42d06a9..c51fc2819d7 100644 --- a/xds/build.gradle +++ b/xds/build.gradle @@ -81,7 +81,11 @@ dependencies { shadow configurations.implementation.getDependencies().minus([nettyDependency]) shadow project(path: ':grpc-netty-shaded', configuration: 'shadow') - signature libraries.signature.java + signature (libraries.signature.java) { + artifact { + extension = "signature" + } + } testRuntimeOnly libraries.netty.tcnative, libraries.netty.tcnative.classes testRuntimeOnly (libraries.netty.tcnative) { diff --git a/xds/src/generated/thirdparty/grpc/com/github/xds/service/orca/v3/OpenRcaServiceGrpc.java b/xds/src/generated/thirdparty/grpc/com/github/xds/service/orca/v3/OpenRcaServiceGrpc.java index de2c7424fca..cb129fd31ba 100644 --- a/xds/src/generated/thirdparty/grpc/com/github/xds/service/orca/v3/OpenRcaServiceGrpc.java +++ b/xds/src/generated/thirdparty/grpc/com/github/xds/service/orca/v3/OpenRcaServiceGrpc.java @@ -70,6 +70,21 @@ public OpenRcaServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOptions c return OpenRcaServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static OpenRcaServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public OpenRcaServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new OpenRcaServiceBlockingV2Stub(channel, callOptions); + } + }; + return OpenRcaServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -191,6 +206,42 @@ public void streamCoreMetrics(com.github.xds.service.orca.v3.OrcaLoadReportReque * a new call to change backend reporting frequency. * */ + public static final class OpenRcaServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private OpenRcaServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected OpenRcaServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new OpenRcaServiceBlockingV2Stub(channel, callOptions); + } + + /** + */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + streamCoreMetrics(com.github.xds.service.orca.v3.OrcaLoadReportRequest request) { + return io.grpc.stub.ClientCalls.blockingV2ServerStreamingCall( + getChannel(), getStreamCoreMetricsMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service OpenRcaService. + *
+   * Out-of-band (OOB) load reporting service for the additional load reporting
+   * agent that does not sit in the request path. Reports are periodically sampled
+   * with sufficient frequency to provide temporal association with requests.
+   * OOB reporting compensates the limitation of in-band reporting in revealing
+   * costs for backends that do not provide a steady stream of telemetry such as
+   * long running stream operations and zero QPS services. This is a server
+   * streaming service, client needs to terminate current RPC and initiate
+   * a new call to change backend reporting frequency.
+   * 
+ */ public static final class OpenRcaServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private OpenRcaServiceBlockingStub( diff --git a/xds/src/generated/thirdparty/grpc/io/envoyproxy/envoy/service/discovery/v3/AggregatedDiscoveryServiceGrpc.java b/xds/src/generated/thirdparty/grpc/io/envoyproxy/envoy/service/discovery/v3/AggregatedDiscoveryServiceGrpc.java index e039c2193e8..b93a5df2b71 100644 --- a/xds/src/generated/thirdparty/grpc/io/envoyproxy/envoy/service/discovery/v3/AggregatedDiscoveryServiceGrpc.java +++ b/xds/src/generated/thirdparty/grpc/io/envoyproxy/envoy/service/discovery/v3/AggregatedDiscoveryServiceGrpc.java @@ -99,6 +99,21 @@ public AggregatedDiscoveryServiceStub newStub(io.grpc.Channel channel, io.grpc.C return AggregatedDiscoveryServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static AggregatedDiscoveryServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public AggregatedDiscoveryServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new AggregatedDiscoveryServiceBlockingV2Stub(channel, callOptions); + } + }; + return AggregatedDiscoveryServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -233,6 +248,52 @@ public io.grpc.stub.StreamObserver */ + public static final class AggregatedDiscoveryServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private AggregatedDiscoveryServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected AggregatedDiscoveryServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new AggregatedDiscoveryServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * This is a gRPC-only API.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + streamAggregatedResources() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getStreamAggregatedResourcesMethod(), getCallOptions()); + } + + /** + */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + deltaAggregatedResources() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getDeltaAggregatedResourcesMethod(), getCallOptions()); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service AggregatedDiscoveryService. + *
+   * See https://github.com/envoyproxy/envoy-api#apis for a description of the role of
+   * ADS and how it is intended to be used by a management server. ADS requests
+   * have the same structure as their singleton xDS counterparts, but can
+   * multiplex many resource types on a single stream. The type_url in the
+   * DiscoveryRequest/DiscoveryResponse provides sufficient information to recover
+   * the multiplexed singleton APIs at the Envoy instance and management server.
+   * 
+ */ public static final class AggregatedDiscoveryServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private AggregatedDiscoveryServiceBlockingStub( diff --git a/xds/src/generated/thirdparty/grpc/io/envoyproxy/envoy/service/load_stats/v3/LoadReportingServiceGrpc.java b/xds/src/generated/thirdparty/grpc/io/envoyproxy/envoy/service/load_stats/v3/LoadReportingServiceGrpc.java index 2adbf02e98a..3bce13a7cf5 100644 --- a/xds/src/generated/thirdparty/grpc/io/envoyproxy/envoy/service/load_stats/v3/LoadReportingServiceGrpc.java +++ b/xds/src/generated/thirdparty/grpc/io/envoyproxy/envoy/service/load_stats/v3/LoadReportingServiceGrpc.java @@ -60,6 +60,21 @@ public LoadReportingServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOpt return LoadReportingServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static LoadReportingServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public LoadReportingServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new LoadReportingServiceBlockingV2Stub(channel, callOptions); + } + }; + return LoadReportingServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -199,6 +214,61 @@ public io.grpc.stub.StreamObserver { + private LoadReportingServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected LoadReportingServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new LoadReportingServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * Advanced API to allow for multi-dimensional load balancing by remote
+     * server. For receiving LB assignments, the steps are:
+     * 1, The management server is configured with per cluster/zone/load metric
+     *    capacity configuration. The capacity configuration definition is
+     *    outside of the scope of this document.
+     * 2. Envoy issues a standard {Stream,Fetch}Endpoints request for the clusters
+     *    to balance.
+     * Independently, Envoy will initiate a StreamLoadStats bidi stream with a
+     * management server:
+     * 1. Once a connection establishes, the management server publishes a
+     *    LoadStatsResponse for all clusters it is interested in learning load
+     *    stats about.
+     * 2. For each cluster, Envoy load balances incoming traffic to upstream hosts
+     *    based on per-zone weights and/or per-instance weights (if specified)
+     *    based on intra-zone LbPolicy. This information comes from the above
+     *    {Stream,Fetch}Endpoints.
+     * 3. When upstream hosts reply, they optionally add header <define header
+     *    name> with ASCII representation of EndpointLoadMetricStats.
+     * 4. Envoy aggregates load reports over the period of time given to it in
+     *    LoadStatsResponse.load_reporting_interval. This includes aggregation
+     *    stats Envoy maintains by itself (total_requests, rpc_errors etc.) as
+     *    well as load metrics from upstream hosts.
+     * 5. When the timer of load_reporting_interval expires, Envoy sends new
+     *    LoadStatsRequest filled with load reports for each cluster.
+     * 6. The management server uses the load reports from all reported Envoys
+     *    from around the world, computes global assignment and prepares traffic
+     *    assignment destined for each zone Envoys are located in. Goto 2.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + streamLoadStats() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getStreamLoadStatsMethod(), getCallOptions()); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service LoadReportingService. + */ public static final class LoadReportingServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private LoadReportingServiceBlockingStub( diff --git a/xds/src/generated/thirdparty/grpc/io/envoyproxy/envoy/service/rate_limit_quota/v3/RateLimitQuotaServiceGrpc.java b/xds/src/generated/thirdparty/grpc/io/envoyproxy/envoy/service/rate_limit_quota/v3/RateLimitQuotaServiceGrpc.java index 2cbb7536d4c..f05d38290dd 100644 --- a/xds/src/generated/thirdparty/grpc/io/envoyproxy/envoy/service/rate_limit_quota/v3/RateLimitQuotaServiceGrpc.java +++ b/xds/src/generated/thirdparty/grpc/io/envoyproxy/envoy/service/rate_limit_quota/v3/RateLimitQuotaServiceGrpc.java @@ -63,6 +63,21 @@ public RateLimitQuotaServiceStub newStub(io.grpc.Channel channel, io.grpc.CallOp return RateLimitQuotaServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static RateLimitQuotaServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public RateLimitQuotaServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new RateLimitQuotaServiceBlockingV2Stub(channel, callOptions); + } + }; + return RateLimitQuotaServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -164,6 +179,39 @@ public io.grpc.stub.StreamObserver */ + public static final class RateLimitQuotaServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private RateLimitQuotaServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected RateLimitQuotaServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new RateLimitQuotaServiceBlockingV2Stub(channel, callOptions); + } + + /** + *
+     * Main communication channel: the data plane sends usage reports to the RLQS server,
+     * and the server asynchronously responding with the assignments.
+     * 
+ */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + streamRateLimitQuotas() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getStreamRateLimitQuotasMethod(), getCallOptions()); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service RateLimitQuotaService. + *
+   * Defines the Rate Limit Quota Service (RLQS).
+   * 
+ */ public static final class RateLimitQuotaServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private RateLimitQuotaServiceBlockingStub( diff --git a/xds/src/generated/thirdparty/grpc/io/envoyproxy/envoy/service/status/v3/ClientStatusDiscoveryServiceGrpc.java b/xds/src/generated/thirdparty/grpc/io/envoyproxy/envoy/service/status/v3/ClientStatusDiscoveryServiceGrpc.java index 3f8874248d0..1a3240875cc 100644 --- a/xds/src/generated/thirdparty/grpc/io/envoyproxy/envoy/service/status/v3/ClientStatusDiscoveryServiceGrpc.java +++ b/xds/src/generated/thirdparty/grpc/io/envoyproxy/envoy/service/status/v3/ClientStatusDiscoveryServiceGrpc.java @@ -96,6 +96,21 @@ public ClientStatusDiscoveryServiceStub newStub(io.grpc.Channel channel, io.grpc return ClientStatusDiscoveryServiceStub.newStub(factory, channel); } + /** + * Creates a new blocking-style stub that supports all types of calls on the service + */ + public static ClientStatusDiscoveryServiceBlockingV2Stub newBlockingV2Stub( + io.grpc.Channel channel) { + io.grpc.stub.AbstractStub.StubFactory factory = + new io.grpc.stub.AbstractStub.StubFactory() { + @java.lang.Override + public ClientStatusDiscoveryServiceBlockingV2Stub newStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new ClientStatusDiscoveryServiceBlockingV2Stub(channel, callOptions); + } + }; + return ClientStatusDiscoveryServiceBlockingV2Stub.newStub(factory, channel); + } + /** * Creates a new blocking-style stub that supports unary and streaming output calls on the service */ @@ -212,6 +227,44 @@ public void fetchClientStatus(io.envoyproxy.envoy.service.status.v3.ClientStatus * also be used to get the current xDS states directly from the client. * */ + public static final class ClientStatusDiscoveryServiceBlockingV2Stub + extends io.grpc.stub.AbstractBlockingStub { + private ClientStatusDiscoveryServiceBlockingV2Stub( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + super(channel, callOptions); + } + + @java.lang.Override + protected ClientStatusDiscoveryServiceBlockingV2Stub build( + io.grpc.Channel channel, io.grpc.CallOptions callOptions) { + return new ClientStatusDiscoveryServiceBlockingV2Stub(channel, callOptions); + } + + /** + */ + @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") + public io.grpc.stub.BlockingClientCall + streamClientStatus() { + return io.grpc.stub.ClientCalls.blockingBidiStreamingCall( + getChannel(), getStreamClientStatusMethod(), getCallOptions()); + } + + /** + */ + public io.envoyproxy.envoy.service.status.v3.ClientStatusResponse fetchClientStatus(io.envoyproxy.envoy.service.status.v3.ClientStatusRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getFetchClientStatusMethod(), getCallOptions(), request); + } + } + + /** + * A stub to allow clients to do limited synchronous rpc calls to service ClientStatusDiscoveryService. + *
+   * CSDS is Client Status Discovery Service. It can be used to get the status of
+   * an xDS-compliant client from the management server's point of view. It can
+   * also be used to get the current xDS states directly from the client.
+   * 
+ */ public static final class ClientStatusDiscoveryServiceBlockingStub extends io.grpc.stub.AbstractBlockingStub { private ClientStatusDiscoveryServiceBlockingStub( diff --git a/xds/src/main/java/io/grpc/xds/CdsLoadBalancer2.java b/xds/src/main/java/io/grpc/xds/CdsLoadBalancer2.java index 3f1eb3e7e4f..04b7663fd35 100644 --- a/xds/src/main/java/io/grpc/xds/CdsLoadBalancer2.java +++ b/xds/src/main/java/io/grpc/xds/CdsLoadBalancer2.java @@ -88,7 +88,7 @@ public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) { } logger.log(XdsLogLevel.DEBUG, "Received resolution result: {0}", resolvedAddresses); this.resolvedAddresses = resolvedAddresses; - xdsClientPool = resolvedAddresses.getAttributes().get(InternalXdsAttributes.XDS_CLIENT_POOL); + xdsClientPool = resolvedAddresses.getAttributes().get(XdsAttributes.XDS_CLIENT_POOL); xdsClient = xdsClientPool.getObject(); CdsConfig config = (CdsConfig) resolvedAddresses.getLoadBalancingPolicyConfig(); logger.log(XdsLogLevel.INFO, "Config: {0}", config); diff --git a/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancer.java b/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancer.java index e4bb28a1b6a..23f89d161e2 100644 --- a/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancer.java +++ b/xds/src/main/java/io/grpc/xds/ClusterImplLoadBalancer.java @@ -52,6 +52,7 @@ import io.grpc.xds.client.XdsClient; import io.grpc.xds.client.XdsLogger; import io.grpc.xds.client.XdsLogger.XdsLogLevel; +import io.grpc.xds.internal.security.SecurityProtocolNegotiators; import io.grpc.xds.internal.security.SslContextProviderSupplier; import io.grpc.xds.orca.OrcaPerRequestUtil; import io.grpc.xds.orca.OrcaPerRequestUtil.OrcaPerRequestReportListener; @@ -114,12 +115,12 @@ public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) { logger.log(XdsLogLevel.DEBUG, "Received resolution result: {0}", resolvedAddresses); Attributes attributes = resolvedAddresses.getAttributes(); if (xdsClientPool == null) { - xdsClientPool = attributes.get(InternalXdsAttributes.XDS_CLIENT_POOL); + xdsClientPool = attributes.get(XdsAttributes.XDS_CLIENT_POOL); assert xdsClientPool != null; xdsClient = xdsClientPool.getObject(); } if (callCounterProvider == null) { - callCounterProvider = attributes.get(InternalXdsAttributes.CALL_COUNTER_PROVIDER); + callCounterProvider = attributes.get(XdsAttributes.CALL_COUNTER_PROVIDER); } ClusterImplConfig config = @@ -236,9 +237,9 @@ public Subchannel createSubchannel(CreateSubchannelArgs args) { .set(ATTR_CLUSTER_LOCALITY, localityAtomicReference); if (GrpcUtil.getFlag("GRPC_EXPERIMENTAL_XDS_AUTHORITY_REWRITE", false)) { String hostname = args.getAddresses().get(0).getAttributes() - .get(InternalXdsAttributes.ATTR_ADDRESS_NAME); + .get(XdsAttributes.ATTR_ADDRESS_NAME); if (hostname != null) { - attrsBuilder.set(InternalXdsAttributes.ATTR_ADDRESS_NAME, hostname); + attrsBuilder.set(XdsAttributes.ATTR_ADDRESS_NAME, hostname); } } args = args.toBuilder().setAddresses(addresses).setAttributes(attrsBuilder.build()).build(); @@ -287,10 +288,10 @@ private List withAdditionalAttributes( List newAddresses = new ArrayList<>(); for (EquivalentAddressGroup eag : addresses) { Attributes.Builder attrBuilder = eag.getAttributes().toBuilder().set( - InternalXdsAttributes.ATTR_CLUSTER_NAME, cluster); + XdsAttributes.ATTR_CLUSTER_NAME, cluster); if (sslContextProviderSupplier != null) { attrBuilder.set( - InternalXdsAttributes.ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER, + SecurityProtocolNegotiators.ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER, sslContextProviderSupplier); } newAddresses.add(new EquivalentAddressGroup(eag.getAddresses(), attrBuilder.build())); @@ -299,8 +300,8 @@ private List withAdditionalAttributes( } private ClusterLocality createClusterLocalityFromAttributes(Attributes addressAttributes) { - Locality locality = addressAttributes.get(InternalXdsAttributes.ATTR_LOCALITY); - String localityName = addressAttributes.get(InternalXdsAttributes.ATTR_LOCALITY_NAME); + Locality locality = addressAttributes.get(XdsAttributes.ATTR_LOCALITY); + String localityName = addressAttributes.get(XdsAttributes.ATTR_LOCALITY_NAME); // Endpoint addresses resolved by ClusterResolverLoadBalancer should always contain // attributes with its locality, including endpoints in LOGICAL_DNS clusters. @@ -431,7 +432,7 @@ public PickResult pickSubchannel(PickSubchannelArgs args) { result = PickResult.withSubchannel(result.getSubchannel(), result.getStreamTracerFactory(), result.getSubchannel().getAttributes().get( - InternalXdsAttributes.ATTR_ADDRESS_NAME)); + XdsAttributes.ATTR_ADDRESS_NAME)); } } return result; diff --git a/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java b/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java index 3ef79699b10..4e08ddc5973 100644 --- a/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java +++ b/xds/src/main/java/io/grpc/xds/ClusterResolverLoadBalancer.java @@ -119,7 +119,7 @@ final class ClusterResolverLoadBalancer extends LoadBalancer { public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) { logger.log(XdsLogLevel.DEBUG, "Received resolution result: {0}", resolvedAddresses); if (xdsClientPool == null) { - xdsClientPool = resolvedAddresses.getAttributes().get(InternalXdsAttributes.XDS_CLIENT_POOL); + xdsClientPool = resolvedAddresses.getAttributes().get(XdsAttributes.XDS_CLIENT_POOL); xdsClient = xdsClientPool.getObject(); } ClusterResolverConfig config = @@ -423,12 +423,12 @@ public void run() { String localityName = localityName(locality); Attributes attr = endpoint.eag().getAttributes().toBuilder() - .set(InternalXdsAttributes.ATTR_LOCALITY, locality) - .set(InternalXdsAttributes.ATTR_LOCALITY_NAME, localityName) - .set(InternalXdsAttributes.ATTR_LOCALITY_WEIGHT, + .set(XdsAttributes.ATTR_LOCALITY, locality) + .set(XdsAttributes.ATTR_LOCALITY_NAME, localityName) + .set(XdsAttributes.ATTR_LOCALITY_WEIGHT, localityLbInfo.localityWeight()) - .set(InternalXdsAttributes.ATTR_SERVER_WEIGHT, weight) - .set(InternalXdsAttributes.ATTR_ADDRESS_NAME, endpoint.hostname()) + .set(XdsAttributes.ATTR_SERVER_WEIGHT, weight) + .set(XdsAttributes.ATTR_ADDRESS_NAME, endpoint.hostname()) .build(); EquivalentAddressGroup eag = new EquivalentAddressGroup( endpoint.eag().getAddresses(), attr); @@ -630,9 +630,9 @@ public void run() { // to handle such it. String localityName = localityName(LOGICAL_DNS_CLUSTER_LOCALITY); Attributes attr = eag.getAttributes().toBuilder() - .set(InternalXdsAttributes.ATTR_LOCALITY, LOGICAL_DNS_CLUSTER_LOCALITY) - .set(InternalXdsAttributes.ATTR_LOCALITY_NAME, localityName) - .set(InternalXdsAttributes.ATTR_ADDRESS_NAME, dnsHostName) + .set(XdsAttributes.ATTR_LOCALITY, LOGICAL_DNS_CLUSTER_LOCALITY) + .set(XdsAttributes.ATTR_LOCALITY_NAME, localityName) + .set(XdsAttributes.ATTR_ADDRESS_NAME, dnsHostName) .build(); eag = new EquivalentAddressGroup(eag.getAddresses(), attr); eag = AddressFilter.setPathFilter(eag, Arrays.asList(priorityName, localityName)); diff --git a/xds/src/main/java/io/grpc/xds/FilterChainMatchingProtocolNegotiators.java b/xds/src/main/java/io/grpc/xds/FilterChainMatchingProtocolNegotiators.java index 37a0e6a8ae0..aaf8d69d2c1 100644 --- a/xds/src/main/java/io/grpc/xds/FilterChainMatchingProtocolNegotiators.java +++ b/xds/src/main/java/io/grpc/xds/FilterChainMatchingProtocolNegotiators.java @@ -17,8 +17,8 @@ package io.grpc.xds; import static com.google.common.base.Preconditions.checkNotNull; -import static io.grpc.xds.InternalXdsAttributes.ATTR_DRAIN_GRACE_NANOS; -import static io.grpc.xds.InternalXdsAttributes.ATTR_FILTER_CHAIN_SELECTOR_MANAGER; +import static io.grpc.xds.XdsAttributes.ATTR_DRAIN_GRACE_NANOS; +import static io.grpc.xds.XdsAttributes.ATTR_FILTER_CHAIN_SELECTOR_MANAGER; import static io.grpc.xds.XdsServerWrapper.ATTR_SERVER_ROUTING_CONFIG; import static io.grpc.xds.internal.security.SecurityProtocolNegotiators.ATTR_SERVER_SSL_CONTEXT_PROVIDER_SUPPLIER; diff --git a/xds/src/main/java/io/grpc/xds/FilterChainSelectorManager.java b/xds/src/main/java/io/grpc/xds/FilterChainSelectorManager.java index 4295d75f59b..b3cc14c6484 100644 --- a/xds/src/main/java/io/grpc/xds/FilterChainSelectorManager.java +++ b/xds/src/main/java/io/grpc/xds/FilterChainSelectorManager.java @@ -18,11 +18,11 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.xds.FilterChainMatchingProtocolNegotiators.FilterChainMatchingHandler.FilterChainSelector; import java.util.Comparator; import java.util.TreeSet; import java.util.concurrent.atomic.AtomicLong; -import javax.annotation.concurrent.GuardedBy; /** * Maintains the current xDS selector and any resources using that selector. When the selector diff --git a/xds/src/main/java/io/grpc/xds/GcpAuthenticationFilter.java b/xds/src/main/java/io/grpc/xds/GcpAuthenticationFilter.java index edd8a09e4ca..6d05e8ffa95 100644 --- a/xds/src/main/java/io/grpc/xds/GcpAuthenticationFilter.java +++ b/xds/src/main/java/io/grpc/xds/GcpAuthenticationFilter.java @@ -22,6 +22,7 @@ import com.google.protobuf.Any; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.Message; +import io.envoyproxy.envoy.extensions.filters.http.gcp_authn.v3.Audience; import io.envoyproxy.envoy.extensions.filters.http.gcp_authn.v3.GcpAuthnFilterConfig; import io.envoyproxy.envoy.extensions.filters.http.gcp_authn.v3.TokenCacheConfig; import io.grpc.CallCredentials; @@ -36,6 +37,7 @@ import io.grpc.Status; import io.grpc.auth.MoreCallCredentials; import io.grpc.xds.Filter.ClientInterceptorBuilder; +import io.grpc.xds.MetadataRegistry.MetadataValueParser; import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.ScheduledExecutorService; @@ -106,7 +108,7 @@ public ClientInterceptor buildClientInterceptor(FilterConfig config, public ClientCall interceptCall( MethodDescriptor method, CallOptions callOptions, Channel next) { - /*String clusterName = callOptions.getOption(InternalXdsAttributes.ATTR_CLUSTER_NAME); + /*String clusterName = callOptions.getOption(XdsAttributes.ATTR_CLUSTER_NAME); if (clusterName == null) { return next.newCall(method, callOptions); }*/ @@ -219,4 +221,23 @@ V getOrInsert(K key, Function create) { return cache.computeIfAbsent(key, create); } } + + static class AudienceMetadataParser implements MetadataValueParser { + + @Override + public String getTypeUrl() { + return "type.googleapis.com/envoy.extensions.filters.http.gcp_authn.v3.Audience"; + } + + @Override + public String parse(Any any) throws InvalidProtocolBufferException { + Audience audience = any.unpack(Audience.class); + String url = audience.getUrl(); + if (url.isEmpty()) { + throw new InvalidProtocolBufferException( + "Audience URL is empty. Metadata value must contain a valid URL."); + } + return url; + } + } } diff --git a/xds/src/main/java/io/grpc/xds/InternalXdsAttributes.java b/xds/src/main/java/io/grpc/xds/InternalXdsAttributes.java index 575bda73f0c..ed70e6f5e78 100644 --- a/xds/src/main/java/io/grpc/xds/InternalXdsAttributes.java +++ b/xds/src/main/java/io/grpc/xds/InternalXdsAttributes.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The gRPC Authors + * Copyright 2024 The gRPC Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,96 +18,19 @@ import io.grpc.Attributes; import io.grpc.EquivalentAddressGroup; -import io.grpc.Grpc; import io.grpc.Internal; -import io.grpc.NameResolver; -import io.grpc.internal.ObjectPool; -import io.grpc.xds.XdsNameResolverProvider.CallCounterProvider; -import io.grpc.xds.client.Locality; -import io.grpc.xds.client.XdsClient; -import io.grpc.xds.internal.security.SslContextProviderSupplier; /** * Internal attributes used for xDS implementation. Do not use. */ @Internal public final class InternalXdsAttributes { - - // TODO(sanjaypujare): move to xds internal package. - /** Attribute key for SslContextProviderSupplier (used from client) for a subchannel. */ - @Grpc.TransportAttr - public static final Attributes.Key - ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER = - Attributes.Key.create("io.grpc.xds.internal.security.SslContextProviderSupplier"); - - /** - * Attribute key for passing around the XdsClient object pool across NameResolver/LoadBalancers. - */ - @NameResolver.ResolutionResultAttr - static final Attributes.Key> XDS_CLIENT_POOL = - Attributes.Key.create("io.grpc.xds.InternalXdsAttributes.xdsClientPool"); - - /** - * Attribute key for obtaining the global provider that provides atomics for aggregating - * outstanding RPCs sent to each cluster. - */ - @NameResolver.ResolutionResultAttr - static final Attributes.Key CALL_COUNTER_PROVIDER = - Attributes.Key.create("io.grpc.xds.InternalXdsAttributes.callCounterProvider"); - - /** - * Map from localities to their weights. - */ - @NameResolver.ResolutionResultAttr - static final Attributes.Key ATTR_LOCALITY_WEIGHT = - Attributes.Key.create("io.grpc.xds.InternalXdsAttributes.localityWeight"); - /** * Name of the cluster that provides this EquivalentAddressGroup. */ - @Internal @EquivalentAddressGroup.Attr public static final Attributes.Key ATTR_CLUSTER_NAME = - Attributes.Key.create("io.grpc.xds.InternalXdsAttributes.clusterName"); - - /** - * The locality that this EquivalentAddressGroup is in. - */ - @EquivalentAddressGroup.Attr - static final Attributes.Key ATTR_LOCALITY = - Attributes.Key.create("io.grpc.xds.InternalXdsAttributes.locality"); - - /** - * The name of the locality that this EquivalentAddressGroup is in. - */ - @EquivalentAddressGroup.Attr - static final Attributes.Key ATTR_LOCALITY_NAME = - Attributes.Key.create("io.grpc.xds.InternalXdsAttributes.localityName"); - - /** - * Endpoint weight for load balancing purposes. - */ - @EquivalentAddressGroup.Attr - static final Attributes.Key ATTR_SERVER_WEIGHT = - Attributes.Key.create("io.grpc.xds.InternalXdsAttributes.serverWeight"); - - /** Name associated with individual address, if available (e.g., DNS name). */ - @EquivalentAddressGroup.Attr - static final Attributes.Key ATTR_ADDRESS_NAME = - Attributes.Key.create("io.grpc.xds.InternalXdsAttributes.addressName"); - - /** - * Filter chain match for network filters. - */ - @Grpc.TransportAttr - static final Attributes.Key - ATTR_FILTER_CHAIN_SELECTOR_MANAGER = Attributes.Key.create( - "io.grpc.xds.InternalXdsAttributes.filterChainSelectorManager"); - - /** Grace time to use when draining. Null for an infinite grace time. */ - @Grpc.TransportAttr - static final Attributes.Key ATTR_DRAIN_GRACE_NANOS = - Attributes.Key.create("io.grpc.xds.InternalXdsAttributes.drainGraceTime"); + XdsAttributes.ATTR_CLUSTER_NAME; private InternalXdsAttributes() {} } diff --git a/xds/src/main/java/io/grpc/xds/MetadataRegistry.java b/xds/src/main/java/io/grpc/xds/MetadataRegistry.java new file mode 100644 index 00000000000..8243b6a6f0f --- /dev/null +++ b/xds/src/main/java/io/grpc/xds/MetadataRegistry.java @@ -0,0 +1,71 @@ +/* + * Copyright 2024 The gRPC Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc.xds; + +import com.google.common.annotations.VisibleForTesting; +import com.google.protobuf.Any; +import com.google.protobuf.InvalidProtocolBufferException; +import io.grpc.xds.GcpAuthenticationFilter.AudienceMetadataParser; +import java.util.HashMap; +import java.util.Map; + +/** + * Registry for parsing cluster metadata values. + * + *

This class maintains a mapping of type URLs to {@link MetadataValueParser} instances, + * allowing for the parsing of different metadata types. + */ +final class MetadataRegistry { + private static final MetadataRegistry INSTANCE = new MetadataRegistry(); + + private final Map supportedParsers = new HashMap<>(); + + private MetadataRegistry() { + registerParser(new AudienceMetadataParser()); + } + + static MetadataRegistry getInstance() { + return INSTANCE; + } + + MetadataValueParser findParser(String typeUrl) { + return supportedParsers.get(typeUrl); + } + + @VisibleForTesting + void registerParser(MetadataValueParser parser) { + supportedParsers.put(parser.getTypeUrl(), parser); + } + + void removeParser(MetadataValueParser parser) { + supportedParsers.remove(parser.getTypeUrl()); + } + + interface MetadataValueParser { + + String getTypeUrl(); + + /** + * Parses the given {@link Any} object into a specific metadata value. + * + * @param any the {@link Any} object to parse. + * @return the parsed metadata value. + * @throws InvalidProtocolBufferException if the parsing fails. + */ + Object parse(Any any) throws InvalidProtocolBufferException; + } +} diff --git a/xds/src/main/java/io/grpc/xds/RingHashLoadBalancer.java b/xds/src/main/java/io/grpc/xds/RingHashLoadBalancer.java index 4f93974b52c..0c4792cb924 100644 --- a/xds/src/main/java/io/grpc/xds/RingHashLoadBalancer.java +++ b/xds/src/main/java/io/grpc/xds/RingHashLoadBalancer.java @@ -102,7 +102,7 @@ public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) { Map serverWeights = new HashMap<>(); long totalWeight = 0L; for (EquivalentAddressGroup eag : addrList) { - Long weight = eag.getAttributes().get(InternalXdsAttributes.ATTR_SERVER_WEIGHT); + Long weight = eag.getAttributes().get(XdsAttributes.ATTR_SERVER_WEIGHT); // Support two ways of server weighing: either multiple instances of the same address // or each address contains a per-address weight attribute. If a weight is not provided, // each occurrence of the address will be counted a weight value of one. @@ -241,7 +241,7 @@ private Status validateAddrList(List addrList) { long totalWeight = 0; for (EquivalentAddressGroup eag : addrList) { - Long weight = eag.getAttributes().get(InternalXdsAttributes.ATTR_SERVER_WEIGHT); + Long weight = eag.getAttributes().get(XdsAttributes.ATTR_SERVER_WEIGHT); if (weight == null) { weight = 1L; diff --git a/xds/src/main/java/io/grpc/xds/SharedXdsClientPoolProvider.java b/xds/src/main/java/io/grpc/xds/SharedXdsClientPoolProvider.java index 779349744ff..2bc7be4a014 100644 --- a/xds/src/main/java/io/grpc/xds/SharedXdsClientPoolProvider.java +++ b/xds/src/main/java/io/grpc/xds/SharedXdsClientPoolProvider.java @@ -21,6 +21,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.MetricRecorder; import io.grpc.internal.ExponentialBackoffPolicy; import io.grpc.internal.GrpcUtil; @@ -40,7 +41,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.ThreadSafe; /** diff --git a/xds/src/main/java/io/grpc/xds/StructOrError.java b/xds/src/main/java/io/grpc/xds/StructOrError.java new file mode 100644 index 00000000000..14f008d191e --- /dev/null +++ b/xds/src/main/java/io/grpc/xds/StructOrError.java @@ -0,0 +1,72 @@ +/* + * Copyright 2024 The gRPC Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc.xds; + +import static com.google.common.base.Preconditions.checkNotNull; + +import com.google.common.annotations.VisibleForTesting; +import javax.annotation.Nullable; + +/** An object or a String error. */ +final class StructOrError { + + /** + * Returns a {@link StructOrError} for the successfully converted data object. + */ + public static StructOrError fromStruct(T struct) { + return new StructOrError<>(struct); + } + + /** + * Returns a {@link StructOrError} for the failure to convert the data object. + */ + public static StructOrError fromError(String errorDetail) { + return new StructOrError<>(errorDetail); + } + + private final String errorDetail; + private final T struct; + + private StructOrError(T struct) { + this.struct = checkNotNull(struct, "struct"); + this.errorDetail = null; + } + + private StructOrError(String errorDetail) { + this.struct = null; + this.errorDetail = checkNotNull(errorDetail, "errorDetail"); + } + + /** + * Returns struct if exists, otherwise null. + */ + @VisibleForTesting + @Nullable + public T getStruct() { + return struct; + } + + /** + * Returns error detail if exists, otherwise null. + */ + @VisibleForTesting + @Nullable + public String getErrorDetail() { + return errorDetail; + } +} + diff --git a/xds/src/main/java/io/grpc/xds/WrrLocalityLoadBalancer.java b/xds/src/main/java/io/grpc/xds/WrrLocalityLoadBalancer.java index 46d2443d36a..3e58efa7c23 100644 --- a/xds/src/main/java/io/grpc/xds/WrrLocalityLoadBalancer.java +++ b/xds/src/main/java/io/grpc/xds/WrrLocalityLoadBalancer.java @@ -74,8 +74,8 @@ public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) { Map localityWeights = new HashMap<>(); for (EquivalentAddressGroup eag : resolvedAddresses.getAddresses()) { Attributes eagAttrs = eag.getAttributes(); - String locality = eagAttrs.get(InternalXdsAttributes.ATTR_LOCALITY_NAME); - Integer localityWeight = eagAttrs.get(InternalXdsAttributes.ATTR_LOCALITY_WEIGHT); + String locality = eagAttrs.get(XdsAttributes.ATTR_LOCALITY_NAME); + Integer localityWeight = eagAttrs.get(XdsAttributes.ATTR_LOCALITY_WEIGHT); if (locality == null) { Status unavailableStatus = Status.UNAVAILABLE.withDescription( diff --git a/xds/src/main/java/io/grpc/xds/XdsAttributes.java b/xds/src/main/java/io/grpc/xds/XdsAttributes.java new file mode 100644 index 00000000000..af8139d8ff4 --- /dev/null +++ b/xds/src/main/java/io/grpc/xds/XdsAttributes.java @@ -0,0 +1,101 @@ +/* + * Copyright 2019 The gRPC Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc.xds; + +import io.grpc.Attributes; +import io.grpc.EquivalentAddressGroup; +import io.grpc.Grpc; +import io.grpc.NameResolver; +import io.grpc.internal.ObjectPool; +import io.grpc.xds.XdsNameResolverProvider.CallCounterProvider; +import io.grpc.xds.client.Locality; +import io.grpc.xds.client.XdsClient; + +/** + * Attributes used for xDS implementation. + */ +final class XdsAttributes { + /** + * Attribute key for passing around the XdsClient object pool across NameResolver/LoadBalancers. + */ + @NameResolver.ResolutionResultAttr + static final Attributes.Key> XDS_CLIENT_POOL = + Attributes.Key.create("io.grpc.xds.XdsAttributes.xdsClientPool"); + + /** + * Attribute key for obtaining the global provider that provides atomics for aggregating + * outstanding RPCs sent to each cluster. + */ + @NameResolver.ResolutionResultAttr + static final Attributes.Key CALL_COUNTER_PROVIDER = + Attributes.Key.create("io.grpc.xds.XdsAttributes.callCounterProvider"); + + /** + * Map from localities to their weights. + */ + @NameResolver.ResolutionResultAttr + static final Attributes.Key ATTR_LOCALITY_WEIGHT = + Attributes.Key.create("io.grpc.xds.XdsAttributes.localityWeight"); + + /** + * Name of the cluster that provides this EquivalentAddressGroup. + */ + @EquivalentAddressGroup.Attr + public static final Attributes.Key ATTR_CLUSTER_NAME = + Attributes.Key.create("io.grpc.xds.XdsAttributes.clusterName"); + + /** + * The locality that this EquivalentAddressGroup is in. + */ + @EquivalentAddressGroup.Attr + static final Attributes.Key ATTR_LOCALITY = + Attributes.Key.create("io.grpc.xds.XdsAttributes.locality"); + + /** + * The name of the locality that this EquivalentAddressGroup is in. + */ + @EquivalentAddressGroup.Attr + static final Attributes.Key ATTR_LOCALITY_NAME = + Attributes.Key.create("io.grpc.xds.XdsAttributes.localityName"); + + /** + * Endpoint weight for load balancing purposes. + */ + @EquivalentAddressGroup.Attr + static final Attributes.Key ATTR_SERVER_WEIGHT = + Attributes.Key.create("io.grpc.xds.XdsAttributes.serverWeight"); + + /** Name associated with individual address, if available (e.g., DNS name). */ + @EquivalentAddressGroup.Attr + static final Attributes.Key ATTR_ADDRESS_NAME = + Attributes.Key.create("io.grpc.xds.XdsAttributes.addressName"); + + /** + * Filter chain match for network filters. + */ + @Grpc.TransportAttr + static final Attributes.Key + ATTR_FILTER_CHAIN_SELECTOR_MANAGER = Attributes.Key.create( + "io.grpc.xds.XdsAttributes.filterChainSelectorManager"); + + /** Grace time to use when draining. Null for an infinite grace time. */ + @Grpc.TransportAttr + static final Attributes.Key ATTR_DRAIN_GRACE_NANOS = + Attributes.Key.create("io.grpc.xds.XdsAttributes.drainGraceTime"); + + private XdsAttributes() {} +} diff --git a/xds/src/main/java/io/grpc/xds/XdsClientMetricReporterImpl.java b/xds/src/main/java/io/grpc/xds/XdsClientMetricReporterImpl.java index fa88237a7ea..0b592eb019e 100644 --- a/xds/src/main/java/io/grpc/xds/XdsClientMetricReporterImpl.java +++ b/xds/src/main/java/io/grpc/xds/XdsClientMetricReporterImpl.java @@ -90,7 +90,7 @@ final class XdsClientMetricReporterImpl implements XdsClientMetricReporter { Arrays.asList("grpc.target", "grpc.xds.server"), Collections.emptyList(), false); RESOURCES_GAUGE = metricInstrumentRegistry.registerLongGauge("grpc.xds_client.resources", "EXPERIMENTAL. Number of xDS resources.", "{resource}", - Arrays.asList("grpc.target", "grpc.xds.authority", "grpc.xds.cache_state", + Arrays.asList("grpc.target", "grpc.xds.cache_state", "grpc.xds.resource_type"), Collections.emptyList(), false); } diff --git a/xds/src/main/java/io/grpc/xds/XdsClusterResource.java b/xds/src/main/java/io/grpc/xds/XdsClusterResource.java index c7789f3d7dd..626d61c1f55 100644 --- a/xds/src/main/java/io/grpc/xds/XdsClusterResource.java +++ b/xds/src/main/java/io/grpc/xds/XdsClusterResource.java @@ -25,6 +25,7 @@ import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.protobuf.Any; import com.google.protobuf.Duration; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.Message; @@ -32,6 +33,7 @@ import com.google.protobuf.util.Durations; import io.envoyproxy.envoy.config.cluster.v3.CircuitBreakers.Thresholds; import io.envoyproxy.envoy.config.cluster.v3.Cluster; +import io.envoyproxy.envoy.config.core.v3.Metadata; import io.envoyproxy.envoy.config.core.v3.RoutingPriority; import io.envoyproxy.envoy.config.core.v3.SocketAddress; import io.envoyproxy.envoy.config.endpoint.v3.ClusterLoadAssignment; @@ -44,12 +46,15 @@ import io.grpc.internal.ServiceConfigUtil.LbConfig; import io.grpc.xds.EnvoyServerProtoData.OutlierDetection; import io.grpc.xds.EnvoyServerProtoData.UpstreamTlsContext; +import io.grpc.xds.MetadataRegistry.MetadataValueParser; import io.grpc.xds.XdsClusterResource.CdsUpdate; import io.grpc.xds.client.XdsClient.ResourceUpdate; import io.grpc.xds.client.XdsResourceType; +import io.grpc.xds.internal.ProtobufJsonConverter; import io.grpc.xds.internal.security.CommonTlsContextUtil; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Set; import javax.annotation.Nullable; @@ -67,6 +72,8 @@ class XdsClusterResource extends XdsResourceType { static final String AGGREGATE_CLUSTER_TYPE_NAME = "envoy.clusters.aggregate"; static final String ADS_TYPE_URL_CDS = "type.googleapis.com/envoy.config.cluster.v3.Cluster"; + private static final String TYPE_URL_CLUSTER_CONFIG = + "type.googleapis.com/envoy.extensions.clusters.aggregate.v3.ClusterConfig"; private static final String TYPE_URL_UPSTREAM_TLS_CONTEXT = "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext"; private static final String TYPE_URL_UPSTREAM_TLS_CONTEXT_V2 = @@ -169,9 +176,62 @@ static CdsUpdate processCluster(Cluster cluster, updateBuilder.filterMetadata( ImmutableMap.copyOf(cluster.getMetadata().getFilterMetadataMap())); + try { + ImmutableMap parsedFilterMetadata = + parseClusterMetadata(cluster.getMetadata()); + updateBuilder.parsedMetadata(parsedFilterMetadata); + } catch (InvalidProtocolBufferException e) { + throw new ResourceInvalidException( + "Failed to parse xDS filter metadata for cluster '" + cluster.getName() + "': " + + e.getMessage(), e); + } + return updateBuilder.build(); } + /** + * Parses cluster metadata into a structured map. + * + *

Values in {@code typed_filter_metadata} take precedence over + * {@code filter_metadata} when keys overlap, following Envoy API behavior. See + * + * Envoy metadata documentation for details. + * + * @param metadata the {@link Metadata} containing the fields to parse. + * @return an immutable map of parsed metadata. + * @throws InvalidProtocolBufferException if parsing {@code typed_filter_metadata} fails. + */ + private static ImmutableMap parseClusterMetadata(Metadata metadata) + throws InvalidProtocolBufferException { + ImmutableMap.Builder parsedMetadata = ImmutableMap.builder(); + + MetadataRegistry registry = MetadataRegistry.getInstance(); + // Process typed_filter_metadata + for (Map.Entry entry : metadata.getTypedFilterMetadataMap().entrySet()) { + String key = entry.getKey(); + Any value = entry.getValue(); + MetadataValueParser parser = registry.findParser(value.getTypeUrl()); + if (parser != null) { + Object parsedValue = parser.parse(value); + parsedMetadata.put(key, parsedValue); + } + } + // building once to reuse in the next loop + ImmutableMap intermediateParsedMetadata = parsedMetadata.build(); + + // Process filter_metadata for remaining keys + for (Map.Entry entry : metadata.getFilterMetadataMap().entrySet()) { + String key = entry.getKey(); + if (!intermediateParsedMetadata.containsKey(key)) { + Struct structValue = entry.getValue(); + Object jsonValue = ProtobufJsonConverter.convertToJson(structValue); + parsedMetadata.put(key, jsonValue); + } + } + + return parsedMetadata.build(); + } + private static StructOrError parseAggregateCluster(Cluster cluster) { String clusterName = cluster.getName(); Cluster.CustomClusterType customType = cluster.getClusterType(); @@ -213,7 +273,7 @@ private static StructOrError parseNonAggregateCluster( continue; } if (threshold.hasMaxRequests()) { - maxConcurrentRequests = (long) threshold.getMaxRequests().getValue(); + maxConcurrentRequests = Integer.toUnsignedLong(threshold.getMaxRequests().getValue()); } } } @@ -571,13 +631,16 @@ abstract static class CdsUpdate implements ResourceUpdate { abstract ImmutableMap filterMetadata(); + abstract ImmutableMap parsedMetadata(); + private static Builder newBuilder(String clusterName) { return new AutoValue_XdsClusterResource_CdsUpdate.Builder() .clusterName(clusterName) .minRingSize(0) .maxRingSize(0) .choiceCount(0) - .filterMetadata(ImmutableMap.of()); + .filterMetadata(ImmutableMap.of()) + .parsedMetadata(ImmutableMap.of()); } static Builder forAggregate(String clusterName, List prioritizedClusterNames) { @@ -696,6 +759,8 @@ Builder leastRequestLbPolicy(Integer choiceCount) { protected abstract Builder filterMetadata(ImmutableMap filterMetadata); + protected abstract Builder parsedMetadata(ImmutableMap parsedMetadata); + abstract CdsUpdate build(); } } diff --git a/xds/src/main/java/io/grpc/xds/XdsCredentialsRegistry.java b/xds/src/main/java/io/grpc/xds/XdsCredentialsRegistry.java index c33b3cd2f85..9dfefaf1a65 100644 --- a/xds/src/main/java/io/grpc/xds/XdsCredentialsRegistry.java +++ b/xds/src/main/java/io/grpc/xds/XdsCredentialsRegistry.java @@ -21,6 +21,7 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableMap; +import com.google.errorprone.annotations.concurrent.GuardedBy; import io.grpc.InternalServiceProviders; import java.util.ArrayList; import java.util.Collections; @@ -31,7 +32,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; -import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.ThreadSafe; /** diff --git a/xds/src/main/java/io/grpc/xds/XdsNameResolver.java b/xds/src/main/java/io/grpc/xds/XdsNameResolver.java index c51709c174c..3c7f4455fde 100644 --- a/xds/src/main/java/io/grpc/xds/XdsNameResolver.java +++ b/xds/src/main/java/io/grpc/xds/XdsNameResolver.java @@ -307,8 +307,8 @@ private void updateResolutionResult() { ConfigOrError parsedServiceConfig = serviceConfigParser.parseServiceConfig(rawServiceConfig); Attributes attrs = Attributes.newBuilder() - .set(InternalXdsAttributes.XDS_CLIENT_POOL, xdsClientPool) - .set(InternalXdsAttributes.CALL_COUNTER_PROVIDER, callCounterProvider) + .set(XdsAttributes.XDS_CLIENT_POOL, xdsClientPool) + .set(XdsAttributes.CALL_COUNTER_PROVIDER, callCounterProvider) .set(InternalConfigSelector.KEY, configSelector) .build(); ResolutionResult result = diff --git a/xds/src/main/java/io/grpc/xds/XdsRouteConfigureResource.java b/xds/src/main/java/io/grpc/xds/XdsRouteConfigureResource.java index 0e065c6ba9a..587c7a437ad 100644 --- a/xds/src/main/java/io/grpc/xds/XdsRouteConfigureResource.java +++ b/xds/src/main/java/io/grpc/xds/XdsRouteConfigureResource.java @@ -78,6 +78,8 @@ class XdsRouteConfigureResource extends XdsResourceType { "type.googleapis.com/envoy.config.route.v3.RouteConfiguration"; private static final String TYPE_URL_FILTER_CONFIG = "type.googleapis.com/envoy.config.route.v3.FilterConfig"; + @VisibleForTesting + static final String HASH_POLICY_FILTER_STATE_KEY = "io.grpc.channel_id"; // TODO(zdapeng): need to discuss how to handle unsupported values. private static final Set SUPPORTED_RETRYABLE_CODES = Collections.unmodifiableSet(EnumSet.of( diff --git a/xds/src/main/java/io/grpc/xds/XdsServerBuilder.java b/xds/src/main/java/io/grpc/xds/XdsServerBuilder.java index b75d5755f6e..928f22c4d5e 100644 --- a/xds/src/main/java/io/grpc/xds/XdsServerBuilder.java +++ b/xds/src/main/java/io/grpc/xds/XdsServerBuilder.java @@ -19,8 +19,8 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; -import static io.grpc.xds.InternalXdsAttributes.ATTR_DRAIN_GRACE_NANOS; -import static io.grpc.xds.InternalXdsAttributes.ATTR_FILTER_CHAIN_SELECTOR_MANAGER; +import static io.grpc.xds.XdsAttributes.ATTR_DRAIN_GRACE_NANOS; +import static io.grpc.xds.XdsAttributes.ATTR_FILTER_CHAIN_SELECTOR_MANAGER; import com.google.common.annotations.VisibleForTesting; import com.google.errorprone.annotations.DoNotCall; diff --git a/xds/src/main/java/io/grpc/xds/client/BootstrapperImpl.java b/xds/src/main/java/io/grpc/xds/client/BootstrapperImpl.java index a48313fd21e..c00685f1781 100644 --- a/xds/src/main/java/io/grpc/xds/client/BootstrapperImpl.java +++ b/xds/src/main/java/io/grpc/xds/client/BootstrapperImpl.java @@ -56,7 +56,7 @@ public abstract class BootstrapperImpl extends Bootstrapper { private static final String SERVER_FEATURE_TRUSTED_XDS_SERVER = "trusted_xds_server"; @VisibleForTesting - static boolean enableXdsFallback = GrpcUtil.getFlag(GRPC_EXPERIMENTAL_XDS_FALLBACK, false); + static boolean enableXdsFallback = GrpcUtil.getFlag(GRPC_EXPERIMENTAL_XDS_FALLBACK, true); protected final XdsLogger logger; @@ -248,7 +248,9 @@ private List parseServerInfos(List rawServerConfigs, XdsLogger lo Object implSpecificConfig = getImplSpecificConfig(serverConfig, serverUri); boolean ignoreResourceDeletion = false; - List serverFeatures = JsonUtil.getListOfStrings(serverConfig, "server_features"); + // "For forward compatibility reasons, the client will ignore any entry in the list that it + // does not understand, regardless of type." + List serverFeatures = JsonUtil.getList(serverConfig, "server_features"); if (serverFeatures != null) { logger.log(XdsLogLevel.INFO, "Server features: {0}", serverFeatures); ignoreResourceDeletion = serverFeatures.contains(SERVER_FEATURE_IGNORE_RESOURCE_DELETION); diff --git a/xds/src/main/java/io/grpc/xds/client/ControlPlaneClient.java b/xds/src/main/java/io/grpc/xds/client/ControlPlaneClient.java index 047f8a2e315..d05942914dc 100644 --- a/xds/src/main/java/io/grpc/xds/client/ControlPlaneClient.java +++ b/xds/src/main/java/io/grpc/xds/client/ControlPlaneClient.java @@ -167,9 +167,10 @@ void adjustResourceSubscription(XdsResourceType resourceType) { resourceStore.startMissingResourceTimers(resources, resourceType); if (resources.isEmpty()) { - // The resource type no longer has subscribing resources; clean up references to it + // The resource type no longer has subscribing resources; clean up references to it, except + // for nonces. If the resource type becomes used again the control plane can ignore requests + // for old/missing nonces. Old type's nonces are dropped when the ADS stream is restarted. versions.remove(resourceType); - adsStream.respNonces.remove(resourceType); } } @@ -308,13 +309,16 @@ private class AdsStream implements XdsTransportFactory.EventHandler, String> respNonces = new HashMap<>(); + // most recently received responses of each resource type. Nonces are never deleted from the + // map; nonces are only discarded once the stream closes because xds_protocol says "the + // management server should not send a DiscoveryResponse for any DiscoveryRequest that has a + // stale nonce." + private final Map respNonces = new HashMap<>(); private final StreamingCall call; private final MethodDescriptor methodDescriptor = AggregatedDiscoveryServiceGrpc.getStreamAggregatedResourcesMethod(); @@ -365,7 +369,7 @@ void sendDiscoveryRequest(XdsResourceType type, String versionInfo, final void sendDiscoveryRequest(XdsResourceType type, Collection resources) { logger.log(XdsLogLevel.INFO, "Sending {0} request for resources: {1}", type, resources); sendDiscoveryRequest(type, versions.getOrDefault(type, ""), resources, - respNonces.getOrDefault(type, ""), null); + respNonces.getOrDefault(type.typeUrl(), ""), null); } @Override @@ -396,6 +400,7 @@ public void run() { boolean isFirstResponse = !responseReceived; responseReceived = true; inError = false; + respNonces.put(response.getTypeUrl(), response.getNonce()); XdsResourceType type = fromTypeUrl(response.getTypeUrl()); if (logger.isLoggable(XdsLogLevel.DEBUG)) { @@ -429,7 +434,6 @@ final void handleRpcResponse(XdsResourceType type, String versionInfo, List call.startRecvMessage(), syncContext); xdsResponseHandler.handleResourceResponse(type, serverInfo, versionInfo, resources, nonce, @@ -446,18 +450,9 @@ private void handleRpcStreamClosed(Status status) { // Reset the backoff sequence if had received a response, or backoff sequence // has never been initialized. retryBackoffPolicy = backoffPolicyProvider.get(); + stopwatch.reset(); } - // FakeClock in tests isn't thread-safe. Schedule the retry timer before notifying callbacks - // to avoid TSAN races, since tests may wait until callbacks are called but then would run - // concurrently with the stopwatch and schedule. - - long elapsed = stopwatch.elapsed(TimeUnit.NANOSECONDS); - long delayNanos = Math.max(0, retryBackoffPolicy.nextBackoffNanos() - elapsed); - - rpcRetryTimer = - syncContext.schedule(new RpcRetryTask(), delayNanos, TimeUnit.NANOSECONDS, timeService); - Status newStatus = status; if (responseReceived) { // A closed ADS stream after a successful response is not considered an error. Servers may @@ -485,9 +480,17 @@ private void handleRpcStreamClosed(Status status) { newStatus.getCode(), newStatus.getDescription(), newStatus.getCause()); } - closed = true; + close(newStatus.asException()); + + // FakeClock in tests isn't thread-safe. Schedule the retry timer before notifying callbacks + // to avoid TSAN races, since tests may wait until callbacks are called but then would run + // concurrently with the stopwatch and schedule. + long elapsed = stopwatch.elapsed(TimeUnit.NANOSECONDS); + long delayNanos = Math.max(0, retryBackoffPolicy.nextBackoffNanos() - elapsed); + rpcRetryTimer = + syncContext.schedule(new RpcRetryTask(), delayNanos, TimeUnit.NANOSECONDS, timeService); + xdsResponseHandler.handleStreamClosed(newStatus, !responseReceived); - cleanUp(); } private void close(Exception error) { diff --git a/xds/src/main/java/io/grpc/xds/client/XdsClient.java b/xds/src/main/java/io/grpc/xds/client/XdsClient.java index 36f8bd591c7..1b53f6778c7 100644 --- a/xds/src/main/java/io/grpc/xds/client/XdsClient.java +++ b/xds/src/main/java/io/grpc/xds/client/XdsClient.java @@ -428,7 +428,7 @@ void handleResourceResponse( void handleStreamClosed(Status error, boolean shouldTryFallback); } - public interface ResourceStore { + interface ResourceStore { /** * Returns the collection of resources currently subscribed to which have an authority matching diff --git a/xds/src/main/java/io/grpc/xds/client/XdsClientImpl.java b/xds/src/main/java/io/grpc/xds/client/XdsClientImpl.java index 791ba3cc62d..4304d1d9e6f 100644 --- a/xds/src/main/java/io/grpc/xds/client/XdsClientImpl.java +++ b/xds/src/main/java/io/grpc/xds/client/XdsClientImpl.java @@ -444,6 +444,9 @@ private Set getResourceKeys(XdsResourceType xdsResourceType) { // cpcForThisStream is null when doing shutdown private void cleanUpResourceTimers(ControlPlaneClient cpcForThisStream) { Collection authoritiesForCpc = getActiveAuthorities(cpcForThisStream); + String target = cpcForThisStream == null ? "null" : cpcForThisStream.getServerInfo().target(); + logger.log(XdsLogLevel.DEBUG, "Cleaning up resource timers for CPC {0}, authorities {1}", + target, authoritiesForCpc); for (Map> subscriberMap : resourceSubscribers.values()) { for (ResourceSubscriber subscriber : subscriberMap.values()) { @@ -957,6 +960,8 @@ public void handleStreamClosed(Status status, boolean shouldTryFallback) { ControlPlaneClient cpcClosed = serverCpClientMap.get(serverInfo); if (cpcClosed == null) { + logger.log(XdsLogLevel.DEBUG, + "Couldn't find closing CPC for {0}, so skipping cleanup and reporting", serverInfo); return; } diff --git a/xds/src/main/java/io/grpc/xds/client/XdsResourceType.java b/xds/src/main/java/io/grpc/xds/client/XdsResourceType.java index 8c3d31604e4..ccb622ff168 100644 --- a/xds/src/main/java/io/grpc/xds/client/XdsResourceType.java +++ b/xds/src/main/java/io/grpc/xds/client/XdsResourceType.java @@ -20,7 +20,6 @@ import static io.grpc.xds.client.XdsClient.canonifyResourceName; import static io.grpc.xds.client.XdsClient.isResourceNameValid; -import com.google.common.annotations.VisibleForTesting; import com.google.protobuf.Any; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.Message; @@ -41,11 +40,7 @@ public abstract class XdsResourceType { static final String TYPE_URL_RESOURCE = "type.googleapis.com/envoy.service.discovery.v3.Resource"; protected static final String TRANSPORT_SOCKET_NAME_TLS = "envoy.transport_sockets.tls"; - @VisibleForTesting - public static final String HASH_POLICY_FILTER_STATE_KEY = "io.grpc.channel_id"; - protected static final String TYPE_URL_CLUSTER_CONFIG = - "type.googleapis.com/envoy.extensions.clusters.aggregate.v3.ClusterConfig"; protected static final String TYPE_URL_TYPED_STRUCT_UDPA = "type.googleapis.com/udpa.type.v1.TypedStruct"; protected static final String TYPE_URL_TYPED_STRUCT = @@ -249,53 +244,4 @@ public ValidatedResourceUpdate(Map> parsedResources, this.errors = errors; } } - - @VisibleForTesting - public static final class StructOrError { - - /** - * Returns a {@link StructOrError} for the successfully converted data object. - */ - public static StructOrError fromStruct(T struct) { - return new StructOrError<>(struct); - } - - /** - * Returns a {@link StructOrError} for the failure to convert the data object. - */ - public static StructOrError fromError(String errorDetail) { - return new StructOrError<>(errorDetail); - } - - private final String errorDetail; - private final T struct; - - private StructOrError(T struct) { - this.struct = checkNotNull(struct, "struct"); - this.errorDetail = null; - } - - private StructOrError(String errorDetail) { - this.struct = null; - this.errorDetail = checkNotNull(errorDetail, "errorDetail"); - } - - /** - * Returns struct if exists, otherwise null. - */ - @VisibleForTesting - @Nullable - public T getStruct() { - return struct; - } - - /** - * Returns error detail if exists, otherwise null. - */ - @VisibleForTesting - @Nullable - public String getErrorDetail() { - return errorDetail; - } - } } diff --git a/xds/src/main/java/io/grpc/xds/internal/ProtobufJsonConverter.java b/xds/src/main/java/io/grpc/xds/internal/ProtobufJsonConverter.java new file mode 100644 index 00000000000..964c28c57e0 --- /dev/null +++ b/xds/src/main/java/io/grpc/xds/internal/ProtobufJsonConverter.java @@ -0,0 +1,61 @@ +/* + * Copyright 2024 The gRPC Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc.xds.internal; + +import com.google.protobuf.Struct; +import com.google.protobuf.Value; +import io.grpc.Internal; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Converter for Protobuf {@link Struct} to JSON-like {@link Map}. + */ +@Internal +public final class ProtobufJsonConverter { + private ProtobufJsonConverter() {} + + public static Map convertToJson(Struct struct) { + Map result = new HashMap<>(); + for (Map.Entry entry : struct.getFieldsMap().entrySet()) { + result.put(entry.getKey(), convertValue(entry.getValue())); + } + return result; + } + + private static Object convertValue(Value value) { + switch (value.getKindCase()) { + case STRUCT_VALUE: + return convertToJson(value.getStructValue()); + case LIST_VALUE: + return value.getListValue().getValuesList().stream() + .map(ProtobufJsonConverter::convertValue) + .collect(Collectors.toList()); + case NUMBER_VALUE: + return value.getNumberValue(); + case STRING_VALUE: + return value.getStringValue(); + case BOOL_VALUE: + return value.getBoolValue(); + case NULL_VALUE: + return null; + default: + throw new IllegalArgumentException("Unknown Value type: " + value.getKindCase()); + } + } +} diff --git a/xds/src/main/java/io/grpc/xds/internal/security/ReferenceCountingMap.java b/xds/src/main/java/io/grpc/xds/internal/security/ReferenceCountingMap.java index b7f56492fa5..08b8f6a325b 100644 --- a/xds/src/main/java/io/grpc/xds/internal/security/ReferenceCountingMap.java +++ b/xds/src/main/java/io/grpc/xds/internal/security/ReferenceCountingMap.java @@ -20,9 +20,9 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; +import com.google.errorprone.annotations.CheckReturnValue; import java.util.HashMap; import java.util.Map; -import javax.annotation.CheckReturnValue; import javax.annotation.concurrent.ThreadSafe; /** diff --git a/xds/src/main/java/io/grpc/xds/internal/security/SecurityProtocolNegotiators.java b/xds/src/main/java/io/grpc/xds/internal/security/SecurityProtocolNegotiators.java index 00659e53de1..c34fab74032 100644 --- a/xds/src/main/java/io/grpc/xds/internal/security/SecurityProtocolNegotiators.java +++ b/xds/src/main/java/io/grpc/xds/internal/security/SecurityProtocolNegotiators.java @@ -20,6 +20,7 @@ import com.google.common.annotations.VisibleForTesting; import io.grpc.Attributes; +import io.grpc.Grpc; import io.grpc.internal.GrpcUtil; import io.grpc.internal.ObjectPool; import io.grpc.netty.GrpcHttp2ConnectionHandler; @@ -28,7 +29,6 @@ import io.grpc.netty.InternalProtocolNegotiator.ProtocolNegotiator; import io.grpc.netty.InternalProtocolNegotiators; import io.grpc.netty.ProtocolNegotiationEvent; -import io.grpc.xds.InternalXdsAttributes; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerContext; @@ -63,6 +63,12 @@ private SecurityProtocolNegotiators() { ATTR_SERVER_SSL_CONTEXT_PROVIDER_SUPPLIER = Attributes.Key.create("io.grpc.xds.internal.security.server.sslContextProviderSupplier"); + /** Attribute key for SslContextProviderSupplier (used from client) for a subchannel. */ + @Grpc.TransportAttr + public static final Attributes.Key + ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER = + Attributes.Key.create("io.grpc.xds.internal.security.SslContextProviderSupplier"); + /** * Returns a {@link InternalProtocolNegotiator.ClientFactory}. * @@ -130,8 +136,7 @@ public AsciiString scheme() { public ChannelHandler newHandler(GrpcHttp2ConnectionHandler grpcHandler) { // check if SslContextProviderSupplier was passed via attributes SslContextProviderSupplier localSslContextProviderSupplier = - grpcHandler.getEagAttributes().get( - InternalXdsAttributes.ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER); + grpcHandler.getEagAttributes().get(ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER); if (localSslContextProviderSupplier == null) { checkNotNull( fallbackProtocolNegotiator, "No TLS config and no fallbackProtocolNegotiator!"); diff --git a/xds/src/test/java/io/grpc/xds/CdsLoadBalancer2Test.java b/xds/src/test/java/io/grpc/xds/CdsLoadBalancer2Test.java index da32332a2a5..82a61e79abf 100644 --- a/xds/src/test/java/io/grpc/xds/CdsLoadBalancer2Test.java +++ b/xds/src/test/java/io/grpc/xds/CdsLoadBalancer2Test.java @@ -160,7 +160,7 @@ public void setUp() { .setAttributes( // Other attributes not used by cluster_resolver LB are omitted. Attributes.newBuilder() - .set(InternalXdsAttributes.XDS_CLIENT_POOL, xdsClientPool) + .set(XdsAttributes.XDS_CLIENT_POOL, xdsClientPool) .build()) .setLoadBalancingPolicyConfig(new CdsConfig(CLUSTER)) .build()); diff --git a/xds/src/test/java/io/grpc/xds/ClusterImplLoadBalancerTest.java b/xds/src/test/java/io/grpc/xds/ClusterImplLoadBalancerTest.java index 0d18af0b04a..1918ea5724c 100644 --- a/xds/src/test/java/io/grpc/xds/ClusterImplLoadBalancerTest.java +++ b/xds/src/test/java/io/grpc/xds/ClusterImplLoadBalancerTest.java @@ -77,6 +77,7 @@ import io.grpc.xds.client.Stats.UpstreamLocalityStats; import io.grpc.xds.client.XdsClient; import io.grpc.xds.internal.security.CommonTlsContextTestsUtil; +import io.grpc.xds.internal.security.SecurityProtocolNegotiators; import io.grpc.xds.internal.security.SslContextProvider; import io.grpc.xds.internal.security.SslContextProviderSupplier; import java.net.SocketAddress; @@ -195,7 +196,7 @@ public void handleResolvedAddresses_propagateToChildPolicy() { FakeLoadBalancer childBalancer = Iterables.getOnlyElement(downstreamBalancers); assertThat(Iterables.getOnlyElement(childBalancer.addresses)).isEqualTo(endpoint); assertThat(childBalancer.config).isSameInstanceAs(weightedTargetConfig); - assertThat(childBalancer.attributes.get(InternalXdsAttributes.XDS_CLIENT_POOL)) + assertThat(childBalancer.attributes.get(XdsAttributes.XDS_CLIENT_POOL)) .isSameInstanceAs(xdsClientPool); } @@ -533,7 +534,7 @@ public void dropRpcsWithRespectToLbConfigDropCategories() { .setAddresses(Collections.singletonList(endpoint)) .setAttributes( Attributes.newBuilder() - .set(InternalXdsAttributes.XDS_CLIENT_POOL, xdsClientPool) + .set(XdsAttributes.XDS_CLIENT_POOL, xdsClientPool) .build()) .setLoadBalancingPolicyConfig(config) .build()); @@ -738,14 +739,14 @@ public void endpointAddressesAttachedWithClusterName() { .build(); Subchannel subchannel = leafBalancer.helper.createSubchannel(args); for (EquivalentAddressGroup eag : subchannel.getAllAddresses()) { - assertThat(eag.getAttributes().get(InternalXdsAttributes.ATTR_CLUSTER_NAME)) + assertThat(eag.getAttributes().get(XdsAttributes.ATTR_CLUSTER_NAME)) .isEqualTo(CLUSTER); } // An address update should also retain the cluster attribute. subchannel.updateAddresses(leafBalancer.addresses); for (EquivalentAddressGroup eag : subchannel.getAllAddresses()) { - assertThat(eag.getAttributes().get(InternalXdsAttributes.ATTR_CLUSTER_NAME)) + assertThat(eag.getAttributes().get(XdsAttributes.ATTR_CLUSTER_NAME)) .isEqualTo(CLUSTER); } } @@ -783,10 +784,10 @@ public void endpointAddressesAttachedWithClusterName() { new FixedResultPicker(PickResult.withSubchannel(subchannel))); } }); - assertThat(subchannel.getAttributes().get(InternalXdsAttributes.ATTR_ADDRESS_NAME)).isEqualTo( + assertThat(subchannel.getAttributes().get(XdsAttributes.ATTR_ADDRESS_NAME)).isEqualTo( "authority-host-name"); for (EquivalentAddressGroup eag : subchannel.getAllAddresses()) { - assertThat(eag.getAttributes().get(InternalXdsAttributes.ATTR_ADDRESS_NAME)) + assertThat(eag.getAttributes().get(XdsAttributes.ATTR_ADDRESS_NAME)) .isEqualTo("authority-host-name"); } @@ -835,9 +836,9 @@ public void endpointAddressesAttachedWithClusterName() { } }); // Sub Channel wrapper args won't have the address name although addresses will. - assertThat(subchannel.getAttributes().get(InternalXdsAttributes.ATTR_ADDRESS_NAME)).isNull(); + assertThat(subchannel.getAttributes().get(XdsAttributes.ATTR_ADDRESS_NAME)).isNull(); for (EquivalentAddressGroup eag : subchannel.getAllAddresses()) { - assertThat(eag.getAttributes().get(InternalXdsAttributes.ATTR_ADDRESS_NAME)) + assertThat(eag.getAttributes().get(XdsAttributes.ATTR_ADDRESS_NAME)) .isEqualTo("authority-host-name"); } @@ -877,7 +878,7 @@ public void endpointAddressesAttachedWithTlsConfig_securityEnabledByDefault() { Subchannel subchannel = leafBalancer.helper.createSubchannel(args); for (EquivalentAddressGroup eag : subchannel.getAllAddresses()) { SslContextProviderSupplier supplier = - eag.getAttributes().get(InternalXdsAttributes.ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER); + eag.getAttributes().get(SecurityProtocolNegotiators.ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER); assertThat(supplier.getTlsContext()).isEqualTo(upstreamTlsContext); } @@ -891,7 +892,8 @@ public void endpointAddressesAttachedWithTlsConfig_securityEnabledByDefault() { assertThat(Iterables.getOnlyElement(downstreamBalancers)).isSameInstanceAs(leafBalancer); subchannel = leafBalancer.helper.createSubchannel(args); // creates new connections for (EquivalentAddressGroup eag : subchannel.getAllAddresses()) { - assertThat(eag.getAttributes().get(InternalXdsAttributes.ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER)) + assertThat( + eag.getAttributes().get(SecurityProtocolNegotiators.ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER)) .isNull(); } @@ -908,14 +910,14 @@ public void endpointAddressesAttachedWithTlsConfig_securityEnabledByDefault() { subchannel = leafBalancer.helper.createSubchannel(args); // creates new connections for (EquivalentAddressGroup eag : subchannel.getAllAddresses()) { SslContextProviderSupplier supplier = - eag.getAttributes().get(InternalXdsAttributes.ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER); + eag.getAttributes().get(SecurityProtocolNegotiators.ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER); assertThat(supplier.isShutdown()).isFalse(); assertThat(supplier.getTlsContext()).isEqualTo(upstreamTlsContext); } loadBalancer.shutdown(); for (EquivalentAddressGroup eag : subchannel.getAllAddresses()) { SslContextProviderSupplier supplier = - eag.getAttributes().get(InternalXdsAttributes.ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER); + eag.getAttributes().get(SecurityProtocolNegotiators.ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER); assertThat(supplier.isShutdown()).isTrue(); } loadBalancer = null; @@ -928,8 +930,8 @@ private void deliverAddressesAndConfig(List addresses, .setAddresses(addresses) .setAttributes( Attributes.newBuilder() - .set(InternalXdsAttributes.XDS_CLIENT_POOL, xdsClientPool) - .set(InternalXdsAttributes.CALL_COUNTER_PROVIDER, callCounterProvider) + .set(XdsAttributes.XDS_CLIENT_POOL, xdsClientPool) + .set(XdsAttributes.CALL_COUNTER_PROVIDER, callCounterProvider) .build()) .setLoadBalancingPolicyConfig(config) .build()); @@ -986,11 +988,11 @@ public String toString() { } Attributes.Builder attributes = Attributes.newBuilder() - .set(InternalXdsAttributes.ATTR_LOCALITY, locality) + .set(XdsAttributes.ATTR_LOCALITY, locality) // Unique but arbitrary string - .set(InternalXdsAttributes.ATTR_LOCALITY_NAME, locality.toString()); + .set(XdsAttributes.ATTR_LOCALITY_NAME, locality.toString()); if (authorityHostname != null) { - attributes.set(InternalXdsAttributes.ATTR_ADDRESS_NAME, authorityHostname); + attributes.set(XdsAttributes.ATTR_ADDRESS_NAME, authorityHostname); } EquivalentAddressGroup eag = new EquivalentAddressGroup(new FakeSocketAddress(name), attributes.build()); diff --git a/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java b/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java index 29c46963da3..9243abba6d3 100644 --- a/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java +++ b/xds/src/test/java/io/grpc/xds/ClusterResolverLoadBalancerTest.java @@ -272,13 +272,13 @@ public void edsClustersWithRingHashEndpointLbPolicy() { // Endpoints in locality1 have no endpoint-level weight specified, so all endpoints within // locality1 are equally weighted. assertThat(addr1.getAddresses()).isEqualTo(endpoint1.getAddresses()); - assertThat(addr1.getAttributes().get(InternalXdsAttributes.ATTR_SERVER_WEIGHT)) + assertThat(addr1.getAttributes().get(XdsAttributes.ATTR_SERVER_WEIGHT)) .isEqualTo(10); assertThat(addr2.getAddresses()).isEqualTo(endpoint2.getAddresses()); - assertThat(addr2.getAttributes().get(InternalXdsAttributes.ATTR_SERVER_WEIGHT)) + assertThat(addr2.getAttributes().get(XdsAttributes.ATTR_SERVER_WEIGHT)) .isEqualTo(10); assertThat(addr3.getAddresses()).isEqualTo(endpoint3.getAddresses()); - assertThat(addr3.getAttributes().get(InternalXdsAttributes.ATTR_SERVER_WEIGHT)) + assertThat(addr3.getAttributes().get(XdsAttributes.ATTR_SERVER_WEIGHT)) .isEqualTo(50 * 60); assertThat(childBalancer.name).isEqualTo(PRIORITY_POLICY_NAME); PriorityLbConfig priorityLbConfig = (PriorityLbConfig) childBalancer.config; @@ -342,7 +342,7 @@ public void edsClustersWithLeastRequestEndpointLbPolicy() { assertThat( childBalancer.addresses.get(0).getAttributes() - .get(InternalXdsAttributes.ATTR_LOCALITY_WEIGHT)).isEqualTo(100); + .get(XdsAttributes.ATTR_LOCALITY_WEIGHT)).isEqualTo(100); } @Test @@ -368,7 +368,7 @@ public void edsClustersEndpointHostname_addedToAddressAttribute() { assertThat( childBalancer.addresses.get(0).getAttributes() - .get(InternalXdsAttributes.ATTR_ADDRESS_NAME)).isEqualTo("hostname1"); + .get(XdsAttributes.ATTR_ADDRESS_NAME)).isEqualTo("hostname1"); } @@ -468,16 +468,16 @@ public void onlyEdsClusters_receivedEndpoints() { assertThat(childProvider3.getPolicyName()).isEqualTo("round_robin"); for (EquivalentAddressGroup eag : childBalancer.addresses) { - if (eag.getAttributes().get(InternalXdsAttributes.ATTR_LOCALITY) == locality1) { - assertThat(eag.getAttributes().get(InternalXdsAttributes.ATTR_LOCALITY_WEIGHT)) + if (eag.getAttributes().get(XdsAttributes.ATTR_LOCALITY) == locality1) { + assertThat(eag.getAttributes().get(XdsAttributes.ATTR_LOCALITY_WEIGHT)) .isEqualTo(70); } - if (eag.getAttributes().get(InternalXdsAttributes.ATTR_LOCALITY) == locality2) { - assertThat(eag.getAttributes().get(InternalXdsAttributes.ATTR_LOCALITY_WEIGHT)) + if (eag.getAttributes().get(XdsAttributes.ATTR_LOCALITY) == locality2) { + assertThat(eag.getAttributes().get(XdsAttributes.ATTR_LOCALITY_WEIGHT)) .isEqualTo(10); } - if (eag.getAttributes().get(InternalXdsAttributes.ATTR_LOCALITY) == locality3) { - assertThat(eag.getAttributes().get(InternalXdsAttributes.ATTR_LOCALITY_WEIGHT)) + if (eag.getAttributes().get(XdsAttributes.ATTR_LOCALITY) == locality3) { + assertThat(eag.getAttributes().get(XdsAttributes.ATTR_LOCALITY_WEIGHT)) .isEqualTo(20); } } @@ -659,7 +659,7 @@ public void handleEdsResource_ignoreLocalitiesWithNoHealthyEndpoints() { FakeLoadBalancer childBalancer = Iterables.getOnlyElement(childBalancers); for (EquivalentAddressGroup eag : childBalancer.addresses) { - assertThat(eag.getAttributes().get(InternalXdsAttributes.ATTR_LOCALITY)).isEqualTo(locality2); + assertThat(eag.getAttributes().get(XdsAttributes.ATTR_LOCALITY)).isEqualTo(locality2); } } @@ -740,9 +740,9 @@ public void onlyLogicalDnsCluster_endpointsResolved() { Collections.emptyList(), "pick_first"); assertAddressesEqual(Arrays.asList(endpoint1, endpoint2), childBalancer.addresses); assertThat(childBalancer.addresses.get(0).getAttributes() - .get(InternalXdsAttributes.ATTR_ADDRESS_NAME)).isEqualTo(DNS_HOST_NAME); + .get(XdsAttributes.ATTR_ADDRESS_NAME)).isEqualTo(DNS_HOST_NAME); assertThat(childBalancer.addresses.get(1).getAttributes() - .get(InternalXdsAttributes.ATTR_ADDRESS_NAME)).isEqualTo(DNS_HOST_NAME); + .get(XdsAttributes.ATTR_ADDRESS_NAME)).isEqualTo(DNS_HOST_NAME); } @@ -1068,7 +1068,7 @@ private void deliverLbConfig(ClusterResolverConfig config) { .setAttributes( // Other attributes not used by cluster_resolver LB are omitted. Attributes.newBuilder() - .set(InternalXdsAttributes.XDS_CLIENT_POOL, xdsClientPool) + .set(XdsAttributes.XDS_CLIENT_POOL, xdsClientPool) .build()) .setLoadBalancingPolicyConfig(config) .build()); diff --git a/xds/src/test/java/io/grpc/xds/CsdsServiceTest.java b/xds/src/test/java/io/grpc/xds/CsdsServiceTest.java index df0687f6706..2c0aae24e52 100644 --- a/xds/src/test/java/io/grpc/xds/CsdsServiceTest.java +++ b/xds/src/test/java/io/grpc/xds/CsdsServiceTest.java @@ -299,7 +299,7 @@ private void verifyResponse(ClientStatusResponse response) { assertThat(response.getConfigCount()).isEqualTo(1); ClientConfig clientConfig = response.getConfig(0); verifyClientConfigNode(clientConfig); - verifyClientConfigNoResources(XDS_CLIENT_NO_RESOURCES, clientConfig); + assertThat(clientConfig.getGenericXdsConfigsList()).isEmpty(); assertThat(clientConfig.getClientScope()).isEmpty(); } @@ -310,7 +310,7 @@ private Collection verifyMultiResponse(ClientStatusResponse response, in for (int i = 0; i < numExpected; i++) { ClientConfig clientConfig = response.getConfig(i); verifyClientConfigNode(clientConfig); - verifyClientConfigNoResources(XDS_CLIENT_NO_RESOURCES, clientConfig); + assertThat(clientConfig.getGenericXdsConfigsList()).isEmpty(); clientScopes.add(clientConfig.getClientScope()); } @@ -382,16 +382,6 @@ public void getClientConfigForXdsClient_subscribedResourcesToGenericXdsConfig() .put(EDS, ImmutableMap.of("subscribedResourceName.EDS", METADATA_ACKED_EDS)) .buildOrThrow(); } - - @Override - public Map> getSubscribedResourceTypesWithTypeUrl() { - return ImmutableMap.of( - LDS.typeUrl(), LDS, - RDS.typeUrl(), RDS, - CDS.typeUrl(), CDS, - EDS.typeUrl(), EDS - ); - } }; ClientConfig clientConfig = CsdsService.getClientConfigForXdsClient(fakeXdsClient, FAKE_CLIENT_SCOPE); @@ -403,31 +393,31 @@ public Map> getSubscribedResourceTypesWithTypeUrl() { // is propagated to the correct resource types. int xdsConfigCount = clientConfig.getGenericXdsConfigsCount(); assertThat(xdsConfigCount).isEqualTo(4); - Map, GenericXdsConfig> configDumps = mapConfigDumps(fakeXdsClient, - clientConfig); - assertThat(configDumps.keySet()).containsExactly(LDS, RDS, CDS, EDS); + Map configDumps = mapConfigDumps(clientConfig); + assertThat(configDumps.keySet()) + .containsExactly(LDS.typeUrl(), RDS.typeUrl(), CDS.typeUrl(), EDS.typeUrl()); // LDS. - GenericXdsConfig genericXdsConfigLds = configDumps.get(LDS); + GenericXdsConfig genericXdsConfigLds = configDumps.get(LDS.typeUrl()); assertThat(genericXdsConfigLds.getName()).isEqualTo("subscribedResourceName.LDS"); assertThat(genericXdsConfigLds.getClientStatus()).isEqualTo(ClientResourceStatus.ACKED); assertThat(genericXdsConfigLds.getVersionInfo()).isEqualTo(VERSION_ACK_LDS); assertThat(genericXdsConfigLds.getXdsConfig()).isEqualTo(RAW_LISTENER); // RDS. - GenericXdsConfig genericXdsConfigRds = configDumps.get(RDS); + GenericXdsConfig genericXdsConfigRds = configDumps.get(RDS.typeUrl()); assertThat(genericXdsConfigRds.getClientStatus()).isEqualTo(ClientResourceStatus.ACKED); assertThat(genericXdsConfigRds.getVersionInfo()).isEqualTo(VERSION_ACK_RDS); assertThat(genericXdsConfigRds.getXdsConfig()).isEqualTo(RAW_ROUTE_CONFIGURATION); // CDS. - GenericXdsConfig genericXdsConfigCds = configDumps.get(CDS); + GenericXdsConfig genericXdsConfigCds = configDumps.get(CDS.typeUrl()); assertThat(genericXdsConfigCds.getClientStatus()).isEqualTo(ClientResourceStatus.ACKED); assertThat(genericXdsConfigCds.getVersionInfo()).isEqualTo(VERSION_ACK_CDS); assertThat(genericXdsConfigCds.getXdsConfig()).isEqualTo(RAW_CLUSTER); // RDS. - GenericXdsConfig genericXdsConfigEds = configDumps.get(EDS); + GenericXdsConfig genericXdsConfigEds = configDumps.get(EDS.typeUrl()); assertThat(genericXdsConfigEds.getClientStatus()).isEqualTo(ClientResourceStatus.ACKED); assertThat(genericXdsConfigEds.getVersionInfo()).isEqualTo(VERSION_ACK_EDS); assertThat(genericXdsConfigEds.getXdsConfig()).isEqualTo(RAW_CLUSTER_LOAD_ASSIGNMENT); @@ -438,23 +428,11 @@ public void getClientConfigForXdsClient_noSubscribedResources() throws Interrupt ClientConfig clientConfig = CsdsService.getClientConfigForXdsClient(XDS_CLIENT_NO_RESOURCES, FAKE_CLIENT_SCOPE); verifyClientConfigNode(clientConfig); - verifyClientConfigNoResources(XDS_CLIENT_NO_RESOURCES, clientConfig); + assertThat(clientConfig.getGenericXdsConfigsList()).isEmpty(); assertThat(clientConfig.getClientScope()).isEqualTo(FAKE_CLIENT_SCOPE); } } - /** - * Assuming {@link MetadataToProtoTests} passes, and metadata converted to corresponding - * config dumps correctly, perform a minimal verification of the general shape of ClientConfig. - */ - private static void verifyClientConfigNoResources(FakeXdsClient xdsClient, - ClientConfig clientConfig) { - int xdsConfigCount = clientConfig.getGenericXdsConfigsCount(); - assertThat(xdsConfigCount).isEqualTo(0); - Map, GenericXdsConfig> configDumps = mapConfigDumps(xdsClient, clientConfig); - assertThat(configDumps).isEmpty(); - } - /** * Assuming {@link EnvoyProtoDataTest#convertNode} passes, perform a minimal check, * just verify the node itself is the one we expect. @@ -465,21 +443,17 @@ private static void verifyClientConfigNode(ClientConfig clientConfig) { assertThat(node).isEqualTo(BOOTSTRAP_NODE.toEnvoyProtoNode()); } - private static Map, GenericXdsConfig> mapConfigDumps(FakeXdsClient client, - ClientConfig config) { - Map, GenericXdsConfig> xdsConfigMap = new HashMap<>(); + private static Map mapConfigDumps(ClientConfig config) { + Map xdsConfigMap = new HashMap<>(); List xdsConfigList = config.getGenericXdsConfigsList(); for (GenericXdsConfig genericXdsConfig : xdsConfigList) { - XdsResourceType type = client.getSubscribedResourceTypesWithTypeUrl() - .get(genericXdsConfig.getTypeUrl()); - assertThat(type).isNotNull(); - assertThat(xdsConfigMap).doesNotContainKey(type); - xdsConfigMap.put(type, genericXdsConfig); + assertThat(xdsConfigMap).doesNotContainKey(genericXdsConfig.getTypeUrl()); + xdsConfigMap.put(genericXdsConfig.getTypeUrl(), genericXdsConfig); } return xdsConfigMap; } - private static class FakeXdsClient extends XdsClient implements XdsClient.ResourceStore { + private static class FakeXdsClient extends XdsClient { protected Map, Map> getSubscribedResourcesMetadata() { return ImmutableMap.of(); @@ -495,24 +469,6 @@ private static class FakeXdsClient extends XdsClient implements XdsClient.Resour public BootstrapInfo getBootstrapInfo() { return BOOTSTRAP_INFO; } - - @Nullable - @Override - public Collection getSubscribedResources( - ServerInfo serverInfo, XdsResourceType type) { - return null; - } - - @Override - public void startMissingResourceTimers(Collection resourceNames, - XdsResourceType resourceType) { - // do nothing - } - - @Override - public Map> getSubscribedResourceTypesWithTypeUrl() { - return ImmutableMap.of(); - } } private static class FakeXdsClientPoolFactory implements XdsClientPoolFactory { diff --git a/xds/src/test/java/io/grpc/xds/GrpcBootstrapperImplTest.java b/xds/src/test/java/io/grpc/xds/GrpcBootstrapperImplTest.java index d2a9bf3316d..192d88177eb 100644 --- a/xds/src/test/java/io/grpc/xds/GrpcBootstrapperImplTest.java +++ b/xds/src/test/java/io/grpc/xds/GrpcBootstrapperImplTest.java @@ -676,6 +676,26 @@ public void serverFeatureIgnoreResourceDeletion_xdsV3() throws XdsInitialization assertThat(serverInfo.ignoreResourceDeletion()).isTrue(); } + @Test + public void serverFeatures_ignoresUnknownValues() throws XdsInitializationException { + String rawData = "{\n" + + " \"xds_servers\": [\n" + + " {\n" + + " \"server_uri\": \"" + SERVER_URI + "\",\n" + + " \"channel_creds\": [\n" + + " {\"type\": \"insecure\"}\n" + + " ],\n" + + " \"server_features\": [null, {}, 3, true, \"unexpected\", \"trusted_xds_server\"]\n" + + " }\n" + + " ]\n" + + "}"; + + bootstrapper.setFileReader(createFileReader(BOOTSTRAP_FILE_PATH, rawData)); + BootstrapInfo info = bootstrapper.bootstrap(); + ServerInfo serverInfo = Iterables.getOnlyElement(info.servers()); + assertThat(serverInfo.isTrustedXdsServer()).isTrue(); + } + @Test public void notFound() { bootstrapper.bootstrapPathFromEnvVar = null; diff --git a/xds/src/test/java/io/grpc/xds/GrpcXdsClientImplDataTest.java b/xds/src/test/java/io/grpc/xds/GrpcXdsClientImplDataTest.java index b0ef0131a6d..654e85143b8 100644 --- a/xds/src/test/java/io/grpc/xds/GrpcXdsClientImplDataTest.java +++ b/xds/src/test/java/io/grpc/xds/GrpcXdsClientImplDataTest.java @@ -50,6 +50,7 @@ import io.envoyproxy.envoy.config.core.v3.DataSource; import io.envoyproxy.envoy.config.core.v3.HttpProtocolOptions; import io.envoyproxy.envoy.config.core.v3.Locality; +import io.envoyproxy.envoy.config.core.v3.Metadata; import io.envoyproxy.envoy.config.core.v3.PathConfigSource; import io.envoyproxy.envoy.config.core.v3.RuntimeFractionalPercent; import io.envoyproxy.envoy.config.core.v3.SelfConfigSource; @@ -84,6 +85,7 @@ import io.envoyproxy.envoy.extensions.filters.common.fault.v3.FaultDelay; import io.envoyproxy.envoy.extensions.filters.http.fault.v3.FaultAbort; import io.envoyproxy.envoy.extensions.filters.http.fault.v3.HTTPFault; +import io.envoyproxy.envoy.extensions.filters.http.gcp_authn.v3.Audience; import io.envoyproxy.envoy.extensions.filters.http.rbac.v3.RBACPerRoute; import io.envoyproxy.envoy.extensions.filters.http.router.v3.Router; import io.envoyproxy.envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager; @@ -127,6 +129,7 @@ import io.grpc.xds.Endpoints.LbEndpoint; import io.grpc.xds.Endpoints.LocalityLbEndpoints; import io.grpc.xds.Filter.FilterConfig; +import io.grpc.xds.MetadataRegistry.MetadataValueParser; import io.grpc.xds.RouteLookupServiceClusterSpecifierPlugin.RlsPluginConfig; import io.grpc.xds.VirtualHost.Route; import io.grpc.xds.VirtualHost.Route.RouteAction; @@ -140,7 +143,6 @@ import io.grpc.xds.client.XdsClient; import io.grpc.xds.client.XdsResourceType; import io.grpc.xds.client.XdsResourceType.ResourceInvalidException; -import io.grpc.xds.client.XdsResourceType.StructOrError; import io.grpc.xds.internal.Matchers; import io.grpc.xds.internal.Matchers.FractionMatcher; import io.grpc.xds.internal.Matchers.HeaderMatcher; @@ -939,7 +941,7 @@ public void parseRouteAction_withHashPolicies() { io.envoyproxy.envoy.config.route.v3.RouteAction.HashPolicy.newBuilder() .setFilterState( FilterState.newBuilder() - .setKey(XdsResourceType.HASH_POLICY_FILTER_STATE_KEY))) + .setKey(XdsRouteConfigureResource.HASH_POLICY_FILTER_STATE_KEY))) .addHashPolicy( io.envoyproxy.envoy.config.route.v3.RouteAction.HashPolicy.newBuilder() .setQueryParameter( @@ -2342,6 +2344,173 @@ public void parseCluster_validateEdsSourceConfig() throws ResourceInvalidExcepti LoadBalancerRegistry.getDefaultRegistry()); } + @Test + public void processCluster_parsesMetadata() + throws ResourceInvalidException, InvalidProtocolBufferException { + MetadataRegistry metadataRegistry = MetadataRegistry.getInstance(); + + MetadataValueParser testParser = + new MetadataValueParser() { + @Override + public String getTypeUrl() { + return "type.googleapis.com/test.Type"; + } + + @Override + public Object parse(Any value) { + assertThat(value.getValue().toStringUtf8()).isEqualTo("test"); + return value.getValue().toStringUtf8() + "_processed"; + } + }; + metadataRegistry.registerParser(testParser); + + Any typedFilterMetadata = Any.newBuilder() + .setTypeUrl("type.googleapis.com/test.Type") + .setValue(ByteString.copyFromUtf8("test")) + .build(); + + Struct filterMetadata = Struct.newBuilder() + .putFields("key1", Value.newBuilder().setStringValue("value1").build()) + .putFields("key2", Value.newBuilder().setNumberValue(42).build()) + .build(); + + Metadata metadata = Metadata.newBuilder() + .putTypedFilterMetadata("TYPED_FILTER_METADATA", typedFilterMetadata) + .putFilterMetadata("FILTER_METADATA", filterMetadata) + .build(); + + Cluster cluster = Cluster.newBuilder() + .setName("cluster-foo.googleapis.com") + .setType(DiscoveryType.EDS) + .setEdsClusterConfig( + EdsClusterConfig.newBuilder() + .setEdsConfig( + ConfigSource.newBuilder() + .setAds(AggregatedConfigSource.getDefaultInstance())) + .setServiceName("service-foo.googleapis.com")) + .setLbPolicy(LbPolicy.ROUND_ROBIN) + .setMetadata(metadata) + .build(); + + CdsUpdate update = XdsClusterResource.processCluster( + cluster, null, LRS_SERVER_INFO, + LoadBalancerRegistry.getDefaultRegistry()); + + ImmutableMap expectedParsedMetadata = ImmutableMap.of( + "TYPED_FILTER_METADATA", "test_processed", + "FILTER_METADATA", ImmutableMap.of( + "key1", "value1", + "key2", 42.0)); + assertThat(update.parsedMetadata()).isEqualTo(expectedParsedMetadata); + metadataRegistry.removeParser(testParser); + } + + @Test + public void processCluster_parsesAudienceMetadata() + throws ResourceInvalidException, InvalidProtocolBufferException { + MetadataRegistry.getInstance(); + + Audience audience = Audience.newBuilder() + .setUrl("https://example.com") + .build(); + + Any audienceMetadata = Any.newBuilder() + .setTypeUrl("type.googleapis.com/envoy.extensions.filters.http.gcp_authn.v3.Audience") + .setValue(audience.toByteString()) + .build(); + + Struct filterMetadata = Struct.newBuilder() + .putFields("key1", Value.newBuilder().setStringValue("value1").build()) + .putFields("key2", Value.newBuilder().setNumberValue(42).build()) + .build(); + + Metadata metadata = Metadata.newBuilder() + .putTypedFilterMetadata("AUDIENCE_METADATA", audienceMetadata) + .putFilterMetadata("FILTER_METADATA", filterMetadata) + .build(); + + Cluster cluster = Cluster.newBuilder() + .setName("cluster-foo.googleapis.com") + .setType(DiscoveryType.EDS) + .setEdsClusterConfig( + EdsClusterConfig.newBuilder() + .setEdsConfig( + ConfigSource.newBuilder() + .setAds(AggregatedConfigSource.getDefaultInstance())) + .setServiceName("service-foo.googleapis.com")) + .setLbPolicy(LbPolicy.ROUND_ROBIN) + .setMetadata(metadata) + .build(); + + CdsUpdate update = XdsClusterResource.processCluster( + cluster, null, LRS_SERVER_INFO, + LoadBalancerRegistry.getDefaultRegistry()); + + ImmutableMap expectedParsedMetadata = ImmutableMap.of( + "AUDIENCE_METADATA", "https://example.com", + "FILTER_METADATA", ImmutableMap.of( + "key1", "value1", + "key2", 42.0)); + assertThat(update.parsedMetadata()).isEqualTo(expectedParsedMetadata); + } + + @Test + public void processCluster_metadataKeyCollision_resolvesToTypedMetadata() + throws ResourceInvalidException, InvalidProtocolBufferException { + MetadataRegistry metadataRegistry = MetadataRegistry.getInstance(); + + MetadataValueParser testParser = + new MetadataValueParser() { + @Override + public String getTypeUrl() { + return "type.googleapis.com/test.Type"; + } + + @Override + public Object parse(Any value) { + return "typedMetadataValue"; + } + }; + metadataRegistry.registerParser(testParser); + + Any typedFilterMetadata = Any.newBuilder() + .setTypeUrl("type.googleapis.com/test.Type") + .setValue(ByteString.copyFromUtf8("test")) + .build(); + + Struct filterMetadata = Struct.newBuilder() + .putFields("key1", Value.newBuilder().setStringValue("filterMetadataValue").build()) + .build(); + + Metadata metadata = Metadata.newBuilder() + .putTypedFilterMetadata("key1", typedFilterMetadata) + .putFilterMetadata("key1", filterMetadata) + .build(); + + Cluster cluster = Cluster.newBuilder() + .setName("cluster-foo.googleapis.com") + .setType(DiscoveryType.EDS) + .setEdsClusterConfig( + EdsClusterConfig.newBuilder() + .setEdsConfig( + ConfigSource.newBuilder() + .setAds(AggregatedConfigSource.getDefaultInstance())) + .setServiceName("service-foo.googleapis.com")) + .setLbPolicy(LbPolicy.ROUND_ROBIN) + .setMetadata(metadata) + .build(); + + CdsUpdate update = XdsClusterResource.processCluster( + cluster, null, LRS_SERVER_INFO, + LoadBalancerRegistry.getDefaultRegistry()); + + ImmutableMap expectedParsedMetadata = ImmutableMap.of( + "key1", "typedMetadataValue"); + assertThat(update.parsedMetadata()).isEqualTo(expectedParsedMetadata); + metadataRegistry.removeParser(testParser); + } + + @Test public void parseServerSideListener_invalidTrafficDirection() throws ResourceInvalidException { Listener listener = diff --git a/xds/src/test/java/io/grpc/xds/GrpcXdsClientImplTestBase.java b/xds/src/test/java/io/grpc/xds/GrpcXdsClientImplTestBase.java index b326eb7d02d..00fbfe669af 100644 --- a/xds/src/test/java/io/grpc/xds/GrpcXdsClientImplTestBase.java +++ b/xds/src/test/java/io/grpc/xds/GrpcXdsClientImplTestBase.java @@ -2898,11 +2898,13 @@ public void edsCleanupNonceAfterUnsubscription() { xdsClient.cancelXdsResourceWatch(XdsEndpointResource.getInstance(), "A.1", edsResourceWatcher); verifySubscribedResourcesMetadataSizes(0, 0, 0, 0); call.verifyRequest(EDS, Arrays.asList(), VERSION_1, "0000", NODE); + // The control plane can send an updated response for the empty subscription list, with a new + // nonce. + call.sendResponse(EDS, Arrays.asList(), VERSION_1, "0001"); - // When re-subscribing, the version and nonce were properly forgotten, so the request is the - // same as the initial request + // When re-subscribing, the version was forgotten but not the nonce xdsClient.watchXdsResource(XdsEndpointResource.getInstance(), "A.1", edsResourceWatcher); - call.verifyRequest(EDS, "A.1", "", "", NODE, Mockito.timeout(2000).times(2)); + call.verifyRequest(EDS, "A.1", "", "0001", NODE, Mockito.timeout(2000)); } @Test @@ -3524,6 +3526,7 @@ public void streamClosedAndRetryWithBackoff() { call.verifyRequest(EDS, EDS_RESOURCE, "", "", NODE); // Management server closes the RPC stream with an error. + fakeClock.forwardNanos(1000L); // Make sure retry isn't based on stopwatch 0 call.sendError(Status.UNKNOWN.asException()); verify(ldsResourceWatcher, Mockito.timeout(1000).times(1)) .onError(errorCaptor.capture()); @@ -4001,6 +4004,25 @@ public void sendToBadUrl() throws Exception { client.shutdown(); } + @Test + public void circuitBreakingConversionOf32bitIntTo64bitLongForMaxRequestNegativeValue() { + DiscoveryRpcCall call = startResourceWatcher(XdsClusterResource.getInstance(), CDS_RESOURCE, + cdsResourceWatcher); + Any clusterCircuitBreakers = Any.pack( + mf.buildEdsCluster(CDS_RESOURCE, null, "round_robin", null, null, false, null, + "envoy.transport_sockets.tls", mf.buildCircuitBreakers(50, -1), null)); + call.sendResponse(CDS, clusterCircuitBreakers, VERSION_1, "0000"); + + // Client sent an ACK CDS request. + call.verifyRequest(CDS, CDS_RESOURCE, VERSION_1, "0000", NODE); + verify(cdsResourceWatcher).onChanged(cdsUpdateCaptor.capture()); + CdsUpdate cdsUpdate = cdsUpdateCaptor.getValue(); + + assertThat(cdsUpdate.clusterName()).isEqualTo(CDS_RESOURCE); + assertThat(cdsUpdate.clusterType()).isEqualTo(ClusterType.EDS); + assertThat(cdsUpdate.maxConcurrentRequests()).isEqualTo(4294967295L); + } + @Test public void sendToNonexistentServer() throws Exception { // Setup xdsClient to fail on stream creation diff --git a/xds/src/test/java/io/grpc/xds/RingHashLoadBalancerTest.java b/xds/src/test/java/io/grpc/xds/RingHashLoadBalancerTest.java index 50c2ef1d549..65fc1527b0c 100644 --- a/xds/src/test/java/io/grpc/xds/RingHashLoadBalancerTest.java +++ b/xds/src/test/java/io/grpc/xds/RingHashLoadBalancerTest.java @@ -1084,7 +1084,7 @@ private static List createWeightedServerAddrs(long... we for (int i = 0; i < weights.length; i++) { SocketAddress addr = new FakeSocketAddress("server" + i); Attributes attr = Attributes.newBuilder().set( - InternalXdsAttributes.ATTR_SERVER_WEIGHT, weights[i]).build(); + XdsAttributes.ATTR_SERVER_WEIGHT, weights[i]).build(); EquivalentAddressGroup eag = new EquivalentAddressGroup(addr, attr); addrs.add(eag); } diff --git a/xds/src/test/java/io/grpc/xds/WrrLocalityLoadBalancerTest.java b/xds/src/test/java/io/grpc/xds/WrrLocalityLoadBalancerTest.java index fcf8c826d86..a87d881563c 100644 --- a/xds/src/test/java/io/grpc/xds/WrrLocalityLoadBalancerTest.java +++ b/xds/src/test/java/io/grpc/xds/WrrLocalityLoadBalancerTest.java @@ -185,7 +185,7 @@ public void localityWeightAttributeNotPropagated() { verify(mockWeightedTargetLb).handleResolvedAddresses(resolvedAddressesCaptor.capture()); //assertThat(resolvedAddressesCaptor.getValue().getAttributes() - // .get(InternalXdsAttributes.ATTR_LOCALITY_WEIGHTS)).isNull(); + // .get(XdsAttributes.ATTR_LOCALITY_WEIGHTS)).isNull(); } @Test @@ -254,9 +254,9 @@ public String toString() { } Attributes.Builder attrBuilder = Attributes.newBuilder() - .set(InternalXdsAttributes.ATTR_LOCALITY_NAME, locality); + .set(XdsAttributes.ATTR_LOCALITY_NAME, locality); if (localityWeight != null) { - attrBuilder.set(InternalXdsAttributes.ATTR_LOCALITY_WEIGHT, localityWeight); + attrBuilder.set(XdsAttributes.ATTR_LOCALITY_WEIGHT, localityWeight); } EquivalentAddressGroup eag = new EquivalentAddressGroup(new FakeSocketAddress(name), diff --git a/xds/src/test/java/io/grpc/xds/XdsClientFallbackTest.java b/xds/src/test/java/io/grpc/xds/XdsClientFallbackTest.java index 39379d43aba..94b49bd94b2 100644 --- a/xds/src/test/java/io/grpc/xds/XdsClientFallbackTest.java +++ b/xds/src/test/java/io/grpc/xds/XdsClientFallbackTest.java @@ -335,10 +335,13 @@ private static void verifyNoSubscribers(ControlPlaneRule rule) { // This test takes a long time because of the 16 sec timeout for non-existent resource @Test - public void connect_then_mainServerDown_fallbackServerUp() throws InterruptedException { + public void connect_then_mainServerDown_fallbackServerUp() throws Exception { mainXdsServer.restartXdsServer(); fallbackServer.restartXdsServer(); - xdsClient = xdsClientPool.getObject(); + XdsClientImpl xdsClient = CommonBootstrapperTestUtils.createXdsClient( + new GrpcBootstrapperImpl().bootstrap(defaultBootstrapOverride()), + DEFAULT_XDS_TRANSPORT_FACTORY, fakeClock, new ExponentialBackoffPolicy.Provider(), + MessagePrinter.INSTANCE, xdsClientMetricReporter); xdsClient.watchXdsResource(XdsListenerResource.getInstance(), MAIN_SERVER, ldsWatcher); @@ -349,7 +352,12 @@ public void connect_then_mainServerDown_fallbackServerUp() throws InterruptedExc verify(rdsWatcher, timeout(5000)).onChanged(any()); mainXdsServer.getServer().shutdownNow(); - TimeUnit.SECONDS.sleep(5); // TODO(lsafran) Use FakeClock so test runs faster + // Sleep for the ADS stream disconnect to be processed and for the retry to fail. Between those + // two sleeps we need the fakeClock to progress by 1 second to restart the ADS stream. + for (int i = 0; i < 5; i++) { + fakeClock.forwardTime(1000, TimeUnit.MILLISECONDS); + TimeUnit.SECONDS.sleep(1); + } // Shouldn't do fallback since all watchers are loaded verify(ldsWatcher, never()).onChanged( @@ -372,7 +380,7 @@ public void connect_then_mainServerDown_fallbackServerUp() throws InterruptedExc XdsListenerResource.LdsUpdate.forApiListener(FALLBACK_HTTP_CONNECTION_MANAGER)); verify(ldsWatcher2, timeout(5000)).onChanged( XdsListenerResource.LdsUpdate.forApiListener(FALLBACK_HTTP_CONNECTION_MANAGER)); - verify(cdsWatcher, timeout(16000)).onChanged(any()); + verify(cdsWatcher, timeout(5000)).onChanged(any()); xdsClient.watchXdsResource( XdsRouteConfigureResource.getInstance(), FALLBACK_RDS_NAME, rdsWatcher3); @@ -381,7 +389,10 @@ public void connect_then_mainServerDown_fallbackServerUp() throws InterruptedExc // Test that resource defined in main but not fallback is handled correctly xdsClient.watchXdsResource( XdsClusterResource.getInstance(), CLUSTER_NAME, cdsWatcher2); - verify(cdsWatcher2, timeout(16000)).onResourceDoesNotExist(eq(CLUSTER_NAME)); + verify(cdsWatcher2, never()).onResourceDoesNotExist(eq(CLUSTER_NAME)); + fakeClock.forwardTime(15000, TimeUnit.MILLISECONDS); // Does not exist timer + verify(cdsWatcher2, timeout(5000)).onResourceDoesNotExist(eq(CLUSTER_NAME)); + xdsClient.shutdown(); } @Test diff --git a/xds/src/test/java/io/grpc/xds/XdsClientMetricReporterImplTest.java b/xds/src/test/java/io/grpc/xds/XdsClientMetricReporterImplTest.java index 9ee3f88d921..df5ab87a1c0 100644 --- a/xds/src/test/java/io/grpc/xds/XdsClientMetricReporterImplTest.java +++ b/xds/src/test/java/io/grpc/xds/XdsClientMetricReporterImplTest.java @@ -17,6 +17,7 @@ package io.grpc.xds; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.AdditionalAnswers.delegatesTo; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; @@ -82,14 +83,14 @@ public class XdsClientMetricReporterImplTest { @Rule public final MockitoRule mocks = MockitoJUnit.rule(); - @Mock - private MetricRecorder mockMetricRecorder; @Mock private XdsClient mockXdsClient; - @Mock - private BatchRecorder mockBatchRecorder; @Captor private ArgumentCaptor gaugeBatchCallbackCaptor; + private MetricRecorder mockMetricRecorder = mock(MetricRecorder.class, + delegatesTo(new MetricRecorderImpl())); + private BatchRecorder mockBatchRecorder = mock(BatchRecorder.class, + delegatesTo(new BatchRecorderImpl())); private XdsClientMetricReporterImpl reporter; @@ -372,6 +373,12 @@ public boolean matches(T instrument) { }); } + static class MetricRecorderImpl implements MetricRecorder { + } + + static class BatchRecorderImpl implements BatchRecorder { + } + static class TestlogHandler extends Handler { List logs = new ArrayList<>(); diff --git a/xds/src/test/java/io/grpc/xds/XdsNameResolverTest.java b/xds/src/test/java/io/grpc/xds/XdsNameResolverTest.java index 6f4c1503cee..d895cecdb10 100644 --- a/xds/src/test/java/io/grpc/xds/XdsNameResolverTest.java +++ b/xds/src/test/java/io/grpc/xds/XdsNameResolverTest.java @@ -755,8 +755,8 @@ public void resolved_simpleCallFailedToRoute_routeWithNonForwardingAction() { assertServiceConfigForLoadBalancingConfig( Collections.singletonList(cluster2), (Map) result.getServiceConfig().getConfig()); - assertThat(result.getAttributes().get(InternalXdsAttributes.XDS_CLIENT_POOL)).isNotNull(); - assertThat(result.getAttributes().get(InternalXdsAttributes.CALL_COUNTER_PROVIDER)).isNotNull(); + assertThat(result.getAttributes().get(XdsAttributes.XDS_CLIENT_POOL)).isNotNull(); + assertThat(result.getAttributes().get(XdsAttributes.CALL_COUNTER_PROVIDER)).isNotNull(); InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY); // Simulates making a call1 RPC. Result selectResult = configSelector.selectConfig( @@ -1156,7 +1156,7 @@ public void resolved_simpleCallSucceeds_routeToWeightedCluster() { assertThat(result.getAddressesOrError().getValue()).isEmpty(); assertServiceConfigForLoadBalancingConfig( Arrays.asList(cluster1, cluster2), (Map) result.getServiceConfig().getConfig()); - assertThat(result.getAttributes().get(InternalXdsAttributes.XDS_CLIENT_POOL)).isNotNull(); + assertThat(result.getAttributes().get(XdsAttributes.XDS_CLIENT_POOL)).isNotNull(); InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY); assertCallSelectClusterResult(call1, configSelector, cluster2, 20.0); assertCallSelectClusterResult(call1, configSelector, cluster1, 20.0); @@ -1207,7 +1207,7 @@ public void resolved_simpleCallSucceeds_routeToRls() { ImmutableList.of(ImmutableMap.of("rls_experimental", expectedRlsLbConfig))))); assertThat(clusterManagerLbConfig).isEqualTo(expectedClusterManagerLbConfig); - assertThat(result.getAttributes().get(InternalXdsAttributes.XDS_CLIENT_POOL)).isNotNull(); + assertThat(result.getAttributes().get(XdsAttributes.XDS_CLIENT_POOL)).isNotNull(); InternalConfigSelector configSelector = result.getAttributes().get(InternalConfigSelector.KEY); assertCallSelectRlsPluginResult( call1, configSelector, "rls-plugin-foo", 20.0); @@ -1345,8 +1345,8 @@ private InternalConfigSelector resolveToClusters() { assertThat(result.getAddressesOrError().getValue()).isEmpty(); assertServiceConfigForLoadBalancingConfig( Arrays.asList(cluster1, cluster2), (Map) result.getServiceConfig().getConfig()); - assertThat(result.getAttributes().get(InternalXdsAttributes.XDS_CLIENT_POOL)).isNotNull(); - assertThat(result.getAttributes().get(InternalXdsAttributes.CALL_COUNTER_PROVIDER)).isNotNull(); + assertThat(result.getAttributes().get(XdsAttributes.XDS_CLIENT_POOL)).isNotNull(); + assertThat(result.getAttributes().get(XdsAttributes.CALL_COUNTER_PROVIDER)).isNotNull(); return result.getAttributes().get(InternalConfigSelector.KEY); } diff --git a/xds/src/test/java/io/grpc/xds/XdsSecurityClientServerTest.java b/xds/src/test/java/io/grpc/xds/XdsSecurityClientServerTest.java index 6915ac6c13e..cd3ef293369 100644 --- a/xds/src/test/java/io/grpc/xds/XdsSecurityClientServerTest.java +++ b/xds/src/test/java/io/grpc/xds/XdsSecurityClientServerTest.java @@ -70,6 +70,7 @@ import io.grpc.xds.client.CommonBootstrapperTestUtils; import io.grpc.xds.internal.Matchers.HeaderMatcher; import io.grpc.xds.internal.security.CommonTlsContextTestsUtil; +import io.grpc.xds.internal.security.SecurityProtocolNegotiators; import io.grpc.xds.internal.security.SslContextProviderSupplier; import io.grpc.xds.internal.security.TlsContextManagerImpl; import io.grpc.xds.internal.security.certprovider.FileWatcherCertificateProviderProvider; @@ -653,7 +654,7 @@ private SimpleServiceGrpc.SimpleServiceBlockingStub getBlockingStub( Attributes attrs = (upstreamTlsContext != null) ? Attributes.newBuilder() - .set(InternalXdsAttributes.ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER, + .set(SecurityProtocolNegotiators.ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER, new SslContextProviderSupplier( upstreamTlsContext, tlsContextManagerForClient)) .build() diff --git a/xds/src/test/java/io/grpc/xds/client/CommonBootstrapperTestUtils.java b/xds/src/test/java/io/grpc/xds/client/CommonBootstrapperTestUtils.java index 27a0d4ba1d9..f3de4549ba9 100644 --- a/xds/src/test/java/io/grpc/xds/client/CommonBootstrapperTestUtils.java +++ b/xds/src/test/java/io/grpc/xds/client/CommonBootstrapperTestUtils.java @@ -23,7 +23,6 @@ import io.grpc.internal.BackoffPolicy; import io.grpc.internal.FakeClock; import io.grpc.internal.JsonParser; -import io.grpc.internal.TimeProvider; import io.grpc.xds.client.Bootstrapper.ServerInfo; import io.grpc.xds.internal.security.CommonTlsContextTestsUtil; import io.grpc.xds.internal.security.TlsContextManagerImpl; @@ -32,28 +31,12 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; public class CommonBootstrapperTestUtils { private static final ChannelCredentials CHANNEL_CREDENTIALS = InsecureChannelCredentials.create(); private static final String SERVER_URI_CUSTOM_AUTHORITY = "trafficdirector2.googleapis.com"; private static final String SERVER_URI_EMPTY_AUTHORITY = "trafficdirector3.googleapis.com"; - - private static final long TIME_INCREMENT = TimeUnit.SECONDS.toNanos(1); - - /** Fake time provider increments time TIME_INCREMENT each call. */ - private static TimeProvider newTimeProvider() { - return new TimeProvider() { - private long count; - - @Override - public long currentTimeNanos() { - return ++count * TIME_INCREMENT; - } - }; - } - private static final String FILE_WATCHER_CONFIG = "{\"path\": \"/etc/secret/certs\"}"; private static final String MESHCA_CONFIG = "{\n" @@ -183,14 +166,28 @@ public static XdsClientImpl createXdsClient(List serverUris, BackoffPolicy.Provider backoffPolicyProvider, MessagePrettyPrinter messagePrinter, XdsClientMetricReporter xdsClientMetricReporter) { - Bootstrapper.BootstrapInfo bootstrapInfo = buildBootStrap(serverUris); + return createXdsClient( + buildBootStrap(serverUris), + xdsTransportFactory, + fakeClock, + backoffPolicyProvider, + messagePrinter, + xdsClientMetricReporter); + } + + public static XdsClientImpl createXdsClient(Bootstrapper.BootstrapInfo bootstrapInfo, + XdsTransportFactory xdsTransportFactory, + FakeClock fakeClock, + BackoffPolicy.Provider backoffPolicyProvider, + MessagePrettyPrinter messagePrinter, + XdsClientMetricReporter xdsClientMetricReporter) { return new XdsClientImpl( xdsTransportFactory, bootstrapInfo, fakeClock.getScheduledExecutorService(), backoffPolicyProvider, fakeClock.getStopwatchSupplier(), - newTimeProvider(), + fakeClock.getTimeProvider(), messagePrinter, new TlsContextManagerImpl(bootstrapInfo), xdsClientMetricReporter); diff --git a/xds/src/test/java/io/grpc/xds/internal/ProtobufJsonConverterTest.java b/xds/src/test/java/io/grpc/xds/internal/ProtobufJsonConverterTest.java new file mode 100644 index 00000000000..86f9be4dda8 --- /dev/null +++ b/xds/src/test/java/io/grpc/xds/internal/ProtobufJsonConverterTest.java @@ -0,0 +1,83 @@ +/* + * Copyright 2024 The gRPC Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.grpc.xds.internal; + +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertEquals; + +import com.google.common.collect.ImmutableMap; +import com.google.protobuf.ListValue; +import com.google.protobuf.Struct; +import com.google.protobuf.Value; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class ProtobufJsonConverterTest { + + @Test + public void testEmptyStruct() { + Struct emptyStruct = Struct.newBuilder().build(); + Map result = ProtobufJsonConverter.convertToJson(emptyStruct); + assertThat(result).isEmpty(); + } + + @Test + public void testStructWithValues() { + Struct struct = Struct.newBuilder() + .putFields("stringKey", Value.newBuilder().setStringValue("stringValue").build()) + .putFields("numberKey", Value.newBuilder().setNumberValue(123.45).build()) + .putFields("boolKey", Value.newBuilder().setBoolValue(true).build()) + .putFields("nullKey", Value.newBuilder().setNullValueValue(0).build()) + .putFields("structKey", Value.newBuilder() + .setStructValue(Struct.newBuilder() + .putFields("nestedKey", Value.newBuilder().setStringValue("nestedValue").build()) + .build()) + .build()) + .putFields("listKey", Value.newBuilder() + .setListValue(ListValue.newBuilder() + .addValues(Value.newBuilder().setNumberValue(1).build()) + .addValues(Value.newBuilder().setStringValue("two").build()) + .addValues(Value.newBuilder().setBoolValue(false).build()) + .build()) + .build()) + .build(); + + Map result = ProtobufJsonConverter.convertToJson(struct); + + Map goldenResult = new HashMap<>(); + goldenResult.put("stringKey", "stringValue"); + goldenResult.put("numberKey", 123.45); + goldenResult.put("boolKey", true); + goldenResult.put("nullKey", null); + goldenResult.put("structKey", ImmutableMap.of("nestedKey", "nestedValue")); + goldenResult.put("listKey", Arrays.asList(1.0, "two", false)); + + assertEquals(goldenResult, result); + } + + @Test(expected = IllegalArgumentException.class) + public void testUnknownValueType() { + Value unknownValue = Value.newBuilder().build(); // Default instance with no kind case set. + ProtobufJsonConverter.convertToJson( + Struct.newBuilder().putFields("unknownKey", unknownValue).build()); + } +} diff --git a/xds/src/test/java/io/grpc/xds/internal/security/SecurityProtocolNegotiatorsTest.java b/xds/src/test/java/io/grpc/xds/internal/security/SecurityProtocolNegotiatorsTest.java index 955c812233a..a0139618f9f 100644 --- a/xds/src/test/java/io/grpc/xds/internal/security/SecurityProtocolNegotiatorsTest.java +++ b/xds/src/test/java/io/grpc/xds/internal/security/SecurityProtocolNegotiatorsTest.java @@ -47,7 +47,6 @@ import io.grpc.netty.ProtocolNegotiationEvent; import io.grpc.xds.EnvoyServerProtoData.DownstreamTlsContext; import io.grpc.xds.EnvoyServerProtoData.UpstreamTlsContext; -import io.grpc.xds.InternalXdsAttributes; import io.grpc.xds.TlsContextManager; import io.grpc.xds.client.Bootstrapper; import io.grpc.xds.client.CommonBootstrapperTestUtils; @@ -134,7 +133,7 @@ public void clientSecurityProtocolNegotiatorNewHandler_withTlsContextAttribute() when(mockHandler.getEagAttributes()) .thenReturn( Attributes.newBuilder() - .set(InternalXdsAttributes.ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER, + .set(SecurityProtocolNegotiators.ATTR_SSL_CONTEXT_PROVIDER_SUPPLIER, new SslContextProviderSupplier(upstreamTlsContext, mockTlsContextManager)) .build()); ChannelHandler newHandler = pn.newHandler(mockHandler);