This will break if
7f1ac34d41,
2f6e2c87ab,
a3a5420922
are reverted:
```
io.grpc.ContextTest > initContextWithCustomClassLoaderWithCustomLogger FAILED
java.lang.ExceptionInInitializerError
at io.grpc.ContextTest$LoadMeWithStaticTestingClassLoader.run(ContextTest.java:789)
at io.grpc.ContextTest.initContextWithCustomClassLoaderWithCustomLogger(ContextTest.java:760)
Caused by:
java.lang.RuntimeException: Storage override had failed to initialize
at io.grpc.Context.storage(Context.java:134)
at io.grpc.Context.current(Context.java:163)
at io.grpc.ContextTest$LoadMeWithStaticTestingClassLoader$1.publish(ContextTest.java:773)
at java.util.logging.Logger.log(Logger.java:738)
at java.util.logging.Logger.doLog(Logger.java:765)
at java.util.logging.Logger.log(Logger.java:875)
at io.grpc.Context.<clinit>(Context.java:122)
... 2 more
```
Using static initialization is possible, but quite complex to handle
logging and circular loading. Lazy loading prevents an entire class of
circular dependencies.
This is only implementing how subchannel state changes are hooked up to channel state APIs. Debates in state semantics and transition rules for loadbalanced channel such as #2873 are not addressed. Any changes in state semantics and transition rules in the future can be easily adapted.
For Netty, this reduces the number of threads necessary for servers (although
until channel is converted, actual number of threads isn't impacted) and
naturally reduces contention and timeout latency.
For InProcess, this gets us closer to allowing applications to provide all
executors, which is especially useful during tests.
Class.forName(String) is understood by ProGuard, removing the need for
manual ProGuard configuration and allows ProGuard to rename the provider
classes. Previously the provider classes could not be renamed.
Fixes#2633
Previously anyone could create metadata keys with a leading ":", due to not having a way to prevent it. This change effectively only allows internal code to make use of this.
It was not convenient to test in some scenarios without having a field in the message. All `SimpleResponse` messages were `equals` to each other. Users might not want to assume reference identity/inequality between server and client for equal/unequal messages even for InProcess. Even with reference identity, it would still be inconvenient if their were hundreds of messages.
To have a non-proto based String to String service instead is another solution, but the usefulness of this proto based service would still be too limited.
* refactor SubchannelImpl -> AbstractSubchannel
The old `SubchannelImpl` is actually not implementing anything, and the old `SubchannelImplImpl` has a weird name.
This has a number of small benefits. First, it makes stack traces
easier to read. For example:
Old class names:
```
ServerCalls$1$1.class
ServerCalls$1.class
ServerCalls$2$1.class
ServerCalls$2.class
```
New class names:
```
ServerCalls$StreamingServerCallHandler.class
ServerCalls$StreamingServerCallHandler$StreamingServerCallListener.class
ServerCalls$UnaryServerCallHandler.class
ServerCalls$UnaryServerCallHandler$UnaryServerCallListener.class
```
This is much easier to read quickly, espcially if line numbers don't
match between HEAD and the code that prints the stack trace.
Another benefit of this is that it drops a class file from the jar
(`EmptyServerCallListener`).
Lastly, it makes it easier in the future to test, since the specific
class can be referenced from a test. Traditionally this class
hasn't been easy to test.
Moved the following APIs from `io.grpc.testing.TestUtils` to `io.grpc.internal.TestUtils`:
`InetSocketAddress testServerAddress(String host, int port)`
`InetSocketAddress testServerAddress(int port)`
`List<String> preferredTestCiphers()`
`File loadCert(String name)`
`X509Certificate loadX509Cert(String fileName)`
`SSLSocketFactory newSslSocketFactoryForCa(Provider provider, File certChainFile)`
`void sleepAtLeast(long millis)`
APIs not to be moved:
`ServerInterceptor recordRequestHeadersInterceptor()`
`ServerInterceptor recordServerCallInterceptor()`
Turns out avoiding log() alone in the static initialization is not
enough. isLoggable() can also be overridden and call back to Context.
We take a another approach, save the exception and log it outside of
the initialization block.
currentThread().getContextClassLoader() was originally used to match
ServiceLoader's default. ServiceLoader is mostly used with SPIs that
exist in the bootclasspath and so the class's ClassLoader would not
work. But in gRPC we have a library in the application's ClassLoader.
Context ClassLoader has been causing problems in any case more than one
application ClassLoader exists, like in Servlet containers, Android, and
plugins. To my knowledge, in every case the context class loader is
different from the provider's class loader, the context class loader has
caused breakage, not success. In addition, since we use static fields
for storing the provider results, using anything but the provider's
class loader is asking to have results that vary simply depending on
which thread called gRPC first.
Fixes#2375