Permalink
Browse files

Load Balancer abstraction.

Refactoring the `ConnectionProvider` interface to make it simple.
Additionally provided a load balancer abstraction to provide higher level load balancing semantics later.
  • Loading branch information...
NiteshKant committed Dec 14, 2015
1 parent a8713a6 commit 3d25c1ee3db104cb78fc84f018da736d60f3bb3c
Showing with 3,415 additions and 2,318 deletions.
  1. +2 −0 rxnetty-common/src/main/java/io/reactivex/netty/HandlerNames.java
  2. +48 −42 rxnetty-common/src/main/java/io/reactivex/netty/channel/AbstractConnectionToChannelBridge.java
  3. +1 −1 rxnetty-common/src/main/java/io/reactivex/netty/channel/AbstractDelegatingConnection.java
  4. +45 −0 rxnetty-common/src/main/java/io/reactivex/netty/channel/ChannelSubscriberEvent.java
  5. +13 −8 rxnetty-common/src/main/java/io/reactivex/netty/channel/Connection.java
  6. +1 −1 rxnetty-common/src/main/java/io/reactivex/netty/channel/ConnectionCreationFailedEvent.java
  7. +16 −3 rxnetty-common/src/main/java/io/reactivex/netty/channel/ConnectionImpl.java
  8. +3 −12 rxnetty-common/src/main/java/io/reactivex/netty/channel/ConnectionInputSubscriberEvent.java
  9. +13 −0 rxnetty-common/src/main/java/io/reactivex/netty/channel/ContentSource.java
  10. +8 −11 rxnetty-common/src/main/java/io/reactivex/netty/channel/DetachedChannelPipeline.java
  11. +1 −1 rxnetty-common/src/main/java/io/reactivex/netty/channel/EmitConnectionEvent.java
  12. +27 −0 rxnetty-common/src/main/java/io/reactivex/netty/client/ChannelProvider.java
  13. +6 −8 ...ava/io/reactivex/netty/client/{internal/EventPublisherFactory.java → ChannelProviderFactory.java}
  14. +11 −79 rxnetty-common/src/main/java/io/reactivex/netty/client/ClientConnectionToChannelBridge.java
  15. +146 −106 rxnetty-common/src/main/java/io/reactivex/netty/client/ClientState.java
  16. +0 −42 rxnetty-common/src/main/java/io/reactivex/netty/client/ConnectionFactory.java
  17. +0 −162 rxnetty-common/src/main/java/io/reactivex/netty/client/ConnectionObservable.java
  18. +8 −244 rxnetty-common/src/main/java/io/reactivex/netty/client/ConnectionProvider.java
  19. +26 −0 rxnetty-common/src/main/java/io/reactivex/netty/client/ConnectionProviderFactory.java
  20. +3 −3 ...tty/protocol/tcp → rxnetty-common/src/main/java/io/reactivex/netty}/client/ConnectionRequest.java
  21. +70 −0 rxnetty-common/src/main/java/io/reactivex/netty/client/Host.java
  22. +110 −0 rxnetty-common/src/main/java/io/reactivex/netty/client/HostConnector.java
  23. +60 −0 rxnetty-common/src/main/java/io/reactivex/netty/client/internal/SingleHostConnectionProvider.java
  24. +50 −0 rxnetty-common/src/main/java/io/reactivex/netty/client/loadbalancer/HostCollector.java
  25. +65 −0 rxnetty-common/src/main/java/io/reactivex/netty/client/loadbalancer/HostHolder.java
  26. +120 −0 rxnetty-common/src/main/java/io/reactivex/netty/client/loadbalancer/LoadBalancerFactory.java
  27. +31 −0 rxnetty-common/src/main/java/io/reactivex/netty/client/loadbalancer/LoadBalancingStrategy.java
  28. +74 −0 rxnetty-common/src/main/java/io/reactivex/netty/client/loadbalancer/NoBufferHostCollector.java
  29. +55 −0 rxnetty-common/src/main/java/io/reactivex/netty/client/loadbalancer/NoHostsAvailableException.java
  30. +23 −43 rxnetty-common/src/main/java/io/reactivex/netty/client/pool/PooledConnectionProvider.java
  31. +51 −102 rxnetty-common/src/main/java/io/reactivex/netty/client/pool/PooledConnectionProviderImpl.java
  32. +60 −0 rxnetty-common/src/main/java/io/reactivex/netty/client/pool/SingleHostPoolingProviderFactory.java
  33. +0 −11 rxnetty-common/src/main/java/io/reactivex/netty/events/ListenersHolder.java
  34. +2 −2 ...protocol/http → rxnetty-common/src/main/java/io/reactivex/netty}/internal/VoidToAnythingCast.java
  35. +1 −1 ...ex/netty/protocol/tcp → rxnetty-common/src/main/java/io/reactivex/netty}/ssl/DefaultSslCodec.java
  36. +1 −2 ...reactivex/netty/protocol/tcp → rxnetty-common/src/main/java/io/reactivex/netty}/ssl/SslCodec.java
  37. +10 −1 rxnetty-common/src/main/java/io/reactivex/netty/test/util/DisabledEventPublisher.java
  38. +0 −134 rxnetty-common/src/main/java/io/reactivex/netty/test/util/EmbeddedConnectionFactory.java
  39. +0 −86 rxnetty-common/src/main/java/io/reactivex/netty/test/util/EmbeddedConnectionProvider.java
  40. +0 −55 rxnetty-common/src/main/java/io/reactivex/netty/test/util/MockEventPublisherFactory.java
  41. +472 −0 rxnetty-common/src/main/java/io/reactivex/netty/test/util/embedded/EmbeddedChannelPipeline.java
  42. +2 −2 ...mon/src/main/java/io/reactivex/netty/test/util/{ → embedded}/EmbeddedChannelPipelineDelegate.java
  43. +102 −0 rxnetty-common/src/main/java/io/reactivex/netty/test/util/embedded/EmbeddedChannelProvider.java
  44. +99 −0 rxnetty-common/src/main/java/io/reactivex/netty/test/util/embedded/EmbeddedChannelTmp.java
  45. +5 −3 ...ty-common/src/main/java/io/reactivex/netty/test/util/{ → embedded}/EmbeddedChannelWithFeeder.java
  46. +64 −0 rxnetty-common/src/main/java/io/reactivex/netty/test/util/embedded/EmbeddedConnectionProvider.java
  47. +13 −14 rxnetty-common/src/test/java/io/reactivex/netty/channel/AbstractConnectionToChannelBridgeTest.java
  48. +5 −6 rxnetty-common/src/test/java/io/reactivex/netty/client/ClientStateTest.java
  49. +196 −0 rxnetty-common/src/test/java/io/reactivex/netty/client/loadbalancer/LoadBalancerFactoryTest.java
  50. +66 −47 rxnetty-common/src/test/java/io/reactivex/netty/client/pool/PooledConnectionProviderImplTest.java
  51. +3 −1 rxnetty-common/src/test/java/io/reactivex/netty/client/pool/PreferCurrentEventLoopHolderTest.java
  52. +40 −28 rxnetty-examples/src/main/java/io/reactivex/netty/examples/http/loadbalancing/HttpLoadBalancer.java
  53. +9 −7 ...xamples/src/main/java/io/reactivex/netty/examples/http/loadbalancing/HttpLoadBalancingClient.java
  54. +8 −5 ...a/io/reactivex/netty/examples/tcp/interceptors/transformation/TransformingInterceptorsServer.java
  55. +77 −0 ...ty-examples/src/main/java/io/reactivex/netty/examples/tcp/loadbalancing/AbstractLoadBalancer.java
  56. +0 −186 ...-examples/src/main/java/io/reactivex/netty/examples/tcp/loadbalancing/RoundRobinLoadBalancer.java
  57. +22 −26 rxnetty-examples/src/main/java/io/reactivex/netty/examples/tcp/loadbalancing/TcpLoadBalancer.java
  58. +8 −5 ...-examples/src/main/java/io/reactivex/netty/examples/tcp/loadbalancing/TcpLoadBalancingClient.java
  59. +1 −1 rxnetty-examples/src/main/java/io/reactivex/netty/examples/tcp/proxy/ProxyServer.java
  60. +3 −4 rxnetty-examples/src/test/java/io/reactivex/netty/examples/tcp/loadbalancing/LoadBalancingTest.java
  61. +22 −7 rxnetty-http/src/main/java/io/reactivex/netty/protocol/http/client/HttpClient.java
  62. +46 −34 rxnetty-http/src/main/java/io/reactivex/netty/protocol/http/client/HttpClientImpl.java
  63. +49 −0 rxnetty-http/src/main/java/io/reactivex/netty/protocol/http/client/internal/HttpChannelProvider.java
  64. +44 −0 ...tp/src/main/java/io/reactivex/netty/protocol/http/client/internal/HttpChannelProviderFactory.java
  65. +3 −3 ...ty-http/src/main/java/io/reactivex/netty/protocol/http/client/internal/HttpClientRequestImpl.java
  66. +2 −2 .../src/main/java/io/reactivex/netty/protocol/http/client/internal/HttpClientToConnectionBridge.java
  67. +0 −75 ...ttp/src/main/java/io/reactivex/netty/protocol/http/client/internal/HttpEventPublisherFactory.java
  68. +2 −2 rxnetty-http/src/main/java/io/reactivex/netty/protocol/http/client/internal/Redirector.java
  69. +10 −8 ...ty-http/src/main/java/io/reactivex/netty/protocol/http/internal/AbstractHttpConnectionBridge.java
  70. +1 −1 rxnetty-http/src/main/java/io/reactivex/netty/protocol/http/server/HttpServer.java
  71. +1 −1 rxnetty-http/src/main/java/io/reactivex/netty/protocol/http/server/HttpServerImpl.java
  72. +0 −132 rxnetty-http/src/test/java/io/reactivex/netty/client/ConnectionProviderTest.java
  73. +3 −21 rxnetty-http/src/test/java/io/reactivex/netty/client/SslClientTest.java
  74. +143 −0 rxnetty-http/src/test/java/io/reactivex/netty/protocol/http/client/EventListenerTest.java
  75. +11 −4 rxnetty-http/src/test/java/io/reactivex/netty/protocol/http/client/HttpClientPoolTest.java
  76. +54 −56 rxnetty-http/src/test/java/io/reactivex/netty/protocol/http/client/HttpClientRule.java
  77. +15 −16 rxnetty-http/src/test/java/io/reactivex/netty/protocol/http/client/HttpClientTest.java
  78. +3 −3 rxnetty-http/src/test/java/io/reactivex/netty/protocol/http/client/HttpRedirectTest.java
  79. +4 −9 ...ttp/src/test/java/io/reactivex/netty/protocol/http/client/internal/HttpClientRequestImplTest.java
  80. +1 −1 ...ttp/src/test/java/io/reactivex/netty/protocol/http/internal/AbstractHttpConnectionBridgeTest.java
  81. +4 −3 rxnetty-http/src/test/java/io/reactivex/netty/protocol/http/server/CookieTest.java
  82. +0 −5 rxnetty-http/src/test/java/io/reactivex/netty/protocol/http/server/HttpServerRule.java
  83. +2 −2 rxnetty-http/src/test/java/io/reactivex/netty/test/util/TcpConnectionRequestMock.java
  84. +0 −2 rxnetty-tcp/src/main/java/io/reactivex/netty/protocol/tcp/TcpHandlerNames.java
  85. +23 −32 rxnetty-tcp/src/main/java/io/reactivex/netty/protocol/tcp/client/ConnectionRequestImpl.java
  86. +32 −0 rxnetty-tcp/src/main/java/io/reactivex/netty/protocol/tcp/client/Interceptor.java
  87. +24 −7 rxnetty-tcp/src/main/java/io/reactivex/netty/protocol/tcp/client/TcpClient.java
  88. +172 −38 rxnetty-tcp/src/main/java/io/reactivex/netty/protocol/tcp/client/TcpClientImpl.java
  89. +0 −99 rxnetty-tcp/src/main/java/io/reactivex/netty/protocol/tcp/client/TcpClientState.java
  90. +34 −0 rxnetty-tcp/src/main/java/io/reactivex/netty/protocol/tcp/client/TransformingInterceptor.java
  91. +2 −1 rxnetty-tcp/src/main/java/io/reactivex/netty/protocol/tcp/client/events/TcpClientEventListener.java
  92. +58 −0 rxnetty-tcp/src/main/java/io/reactivex/netty/protocol/tcp/client/internal/TcpChannelProvider.java
  93. +45 −0 ...-tcp/src/main/java/io/reactivex/netty/protocol/tcp/client/internal/TcpChannelProviderFactory.java
  94. +0 −63 ...y-tcp/src/main/java/io/reactivex/netty/protocol/tcp/client/internal/TcpEventPublisherFactory.java
  95. +1 −1 rxnetty-tcp/src/main/java/io/reactivex/netty/protocol/tcp/server/TcpServer.java
  96. +14 −6 ...-tcp/src/main/java/io/reactivex/netty/protocol/tcp/server/TcpServerConnectionToChannelBridge.java
  97. +1 −1 rxnetty-tcp/src/main/java/io/reactivex/netty/protocol/tcp/server/TcpServerImpl.java
  98. +20 −84 rxnetty-tcp/src/main/java/io/reactivex/netty/protocol/tcp/server/TcpServerInterceptorChain.java
  99. +2 −2 rxnetty-tcp/src/main/java/io/reactivex/netty/protocol/tcp/server/TcpServerState.java
  100. +5 −9 rxnetty-tcp/src/test/java/io/reactivex/netty/client/ClientStateTest.java
  101. +41 −64 rxnetty-tcp/src/test/java/io/reactivex/netty/protocol/tcp/client/ConnectionRequestImplTest.java
  102. +116 −0 rxnetty-tcp/src/test/java/io/reactivex/netty/protocol/tcp/client/EventListenerTest.java
  103. +1 −2 rxnetty-tcp/src/test/java/io/reactivex/netty/protocol/tcp/client/PoolingWithRealChannelTest.java
  104. +29 −16 rxnetty-tcp/src/test/java/io/reactivex/netty/protocol/tcp/client/TcpClientImplTest.java
  105. +15 −6 rxnetty-tcp/src/test/java/io/reactivex/netty/protocol/tcp/client/TcpClientRule.java
  106. +3 −4 ...p/src/test/java/io/reactivex/netty/protocol/tcp/server/UnexpectedConnectionHandlerErrorsTest.java
  107. +1 −1 settings.gradle
@@ -21,6 +21,8 @@
*/
public enum HandlerNames {
+ SslHandler("ssl-handler"),
+ SslConnectionEmissionHandler("ssl-connection-emitter"),
WireLogging("wire-logging-handler"),
PrimitiveConverter("primitive-converter"),
ClientReadTimeoutHandler("client-read-timeout-handler"),
@@ -42,7 +42,7 @@
*
* Lazy subscriptions are allowed on {@link Connection#getInput()} if and only if the channel is configured to
* not read data automatically (i.e. {@link ChannelOption#AUTO_READ} is set to {@code false}). Otherwise,
- * if {@link Connection#getInput()} is subscribed lazily, the subscriber always recieves an error. The content
+ * if {@link Connection#getInput()} is subscribed lazily, the subscriber always receives an error. The content
* in this case is disposed upon reading.
*
* @param <R> Type read from the connection held by this handler.
@@ -77,7 +77,7 @@
protected ConnectionEventListener eventListener;
protected EventPublisher eventPublisher;
- private Subscriber<? super Connection<R, W>> newConnectionSub;
+ private Subscriber<? super Channel> newChannelSub;
private ReadProducer<R> readProducer;
private boolean raiseErrorOnInputSubscription;
private boolean connectionEmitted;
@@ -105,13 +105,6 @@ protected AbstractConnectionToChannelBridge(String thisHandlerName,
this.eventPublisherAttributeKey = eventPublisherAttributeKey;
}
- protected AbstractConnectionToChannelBridge(String thisHandlerName, Subscriber<? super Connection<R, W>> connSub,
- AttributeKey<ConnectionEventListener> eventListenerAttributeKey,
- AttributeKey<EventPublisher> eventPublisherAttributeKey) {
- this(thisHandlerName, eventListenerAttributeKey, eventPublisherAttributeKey);
- newConnectionSub = connSub;
- }
-
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
if (null == eventListener && null == eventPublisher) {
@@ -136,6 +129,15 @@ public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
super.handlerAdded(ctx);
}
+ @Override
+ public void channelInactive(ChannelHandlerContext ctx) throws Exception {
+ if (!connectionEmitted && isValidToEmit(newChannelSub)) {
+ emitNewConnection(ctx.channel());
+ connectionEmitted = true;
+ }
+ super.channelInactive(ctx);
+ }
+
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
@@ -151,29 +153,29 @@ public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof EmitConnectionEvent) {
if (!connectionEmitted) {
- createNewConnection(ctx.channel());
+ emitNewConnection(ctx.channel());
connectionEmitted = true;
}
} else if (evt instanceof ConnectionCreationFailedEvent) {
- if (isValidToEmit(newConnectionSub)) {
- newConnectionSub.onError(((ConnectionCreationFailedEvent)evt).getThrowable());
+ if (isValidToEmit(newChannelSub)) {
+ newChannelSub.onError(((ConnectionCreationFailedEvent)evt).getThrowable());
}
- } else if (evt instanceof ConnectionSubscriberEvent) {
+ } else if (evt instanceof ChannelSubscriberEvent) {
@SuppressWarnings("unchecked")
- final ConnectionSubscriberEvent<R, W> connectionSubscriberEvent = (ConnectionSubscriberEvent<R, W>) evt;
+ final ChannelSubscriberEvent<R, W> channelSubscriberEvent = (ChannelSubscriberEvent<R, W>) evt;
- newConnectionSubscriber(connectionSubscriberEvent);
+ newConnectionSubscriber(channelSubscriberEvent);
} else if (evt instanceof ConnectionInputSubscriberEvent) {
@SuppressWarnings("unchecked")
ConnectionInputSubscriberEvent<R, W> event = (ConnectionInputSubscriberEvent<R, W>) evt;
- newConnectionInputSubscriber(ctx.channel(), event.getSubscriber(), event.getConnection(), false);
+ newConnectionInputSubscriber(ctx.channel(), event.getSubscriber(), false);
} else if (evt instanceof ConnectionInputSubscriberResetEvent) {
resetConnectionInputSubscriber();
} else if (evt instanceof ConnectionInputSubscriberReplaceEvent) {
@SuppressWarnings("unchecked")
ConnectionInputSubscriberReplaceEvent<R, W> event = (ConnectionInputSubscriberReplaceEvent<R, W>) evt;
- replaceConnectionInputSubscriber(event);
+ replaceConnectionInputSubscriber(ctx.channel(), event);
}
super.userEventTriggered(ctx, evt);
@@ -205,8 +207,8 @@ public boolean shouldReadMore(ChannelHandlerContext ctx) {
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
- if (!connectionEmitted && isValidToEmit(newConnectionSub)) {
- newConnectionSub.onError(cause);
+ if (!connectionEmitted && isValidToEmit(newChannelSub)) {
+ newChannelSub.onError(cause);
} else if (isValidToEmitToReadSubscriber(readProducer)) {
readProducer.sendOnError(cause);
} else {
@@ -228,34 +230,38 @@ protected boolean connectionInputSubscriberExists(Channel channel) {
return null != readProducer && null != readProducer.subscriber && !readProducer.subscriber.isUnsubscribed();
}
- protected void onNewReadSubscriber(Connection<R, W> connection, Subscriber<? super R> subscriber) {
+ protected void onNewReadSubscriber(Subscriber<? super R> subscriber) {
// NOOP
}
- protected final void checkEagerSubscriptionIfConfigured(Connection<R, W> connection, Channel channel) {
+ protected final void checkEagerSubscriptionIfConfigured(Channel channel) {
if (channel.config().isAutoRead() && null == readProducer) {
// If the channel is set to auto-read and there is no eager subscription then, we should raise errors
// when a subscriber arrives.
raiseErrorOnInputSubscription = true;
- final Subscriber<? super R> discardAll = ConnectionInputSubscriberEvent.discardAllInput(connection)
+ final Subscriber<? super R> discardAll = ConnectionInputSubscriberEvent.discardAllInput()
.getSubscriber();
final ReadProducer<R> producer = new ReadProducer<>(discardAll, channel);
discardAll.setProducer(producer);
readProducer = producer;
}
}
- protected final Subscriber<? super Connection<R, W>> getNewConnectionSub() {
- return newConnectionSub;
+ protected final Subscriber<? super Channel> getNewChannelSub() {
+ return newChannelSub;
}
- private void createNewConnection(Channel channel) {
- if (isValidToEmit(newConnectionSub)) {
- Connection<R, W> connection = ConnectionImpl.create(channel, eventListener, eventPublisher);
- newConnectionSub.onNext(connection);
- connectionEmitted = true;
- checkEagerSubscriptionIfConfigured(connection, channel);
- newConnectionSub.onCompleted();
+ private void emitNewConnection(Channel channel) {
+ if (isValidToEmit(newChannelSub)) {
+ try {
+ newChannelSub.onNext(channel);
+ connectionEmitted = true;
+ checkEagerSubscriptionIfConfigured(channel);
+ newChannelSub.onCompleted();
+ } catch (Exception e) {
+ logger.error("Error emitting a new connection. Closing this channel.", e);
+ channel.close();
+ }
} else {
channel.close(); // Closing the connection if not sent to a subscriber.
}
@@ -271,39 +277,39 @@ private void resetConnectionInputSubscriber() {
}
private void newConnectionInputSubscriber(final Channel channel, final Subscriber<? super R> subscriber,
- final Connection<R, W> connection, boolean replace) {
+ boolean replace) {
final Subscriber<? super R> connInputSub = null == readProducer ? null : readProducer.subscriber;
if (isValidToEmit(connInputSub)) {
if (!replace) {
/*Allow only once concurrent input subscriber but allow concatenated subscribers*/
subscriber.onError(ONLY_ONE_CONN_INPUT_SUB_ALLOWED);
} else {
- setNewReadProducer(channel, subscriber, connection);
+ setNewReadProducer(channel, subscriber);
connInputSub.onCompleted();
}
} else if (raiseErrorOnInputSubscription) {
subscriber.onError(LAZY_CONN_INPUT_SUB);
} else {
- setNewReadProducer(channel, subscriber, connection);
+ setNewReadProducer(channel, subscriber);
}
}
- private void setNewReadProducer(Channel channel, Subscriber<? super R> subscriber, Connection<R, W> connection) {
+ private void setNewReadProducer(Channel channel, Subscriber<? super R> subscriber) {
final ReadProducer<R> producer = new ReadProducer<>(subscriber, channel);
subscriber.setProducer(producer);
- onNewReadSubscriber(connection, subscriber);
+ onNewReadSubscriber(subscriber);
readProducer = producer;
}
- private void replaceConnectionInputSubscriber(ConnectionInputSubscriberReplaceEvent<R, W> event) {
+ private void replaceConnectionInputSubscriber(Channel channel, ConnectionInputSubscriberReplaceEvent<R, W> event) {
ConnectionInputSubscriberEvent<R, W> newSubEvent = event.getNewSubEvent();
- newConnectionInputSubscriber(newSubEvent.getConnection().unsafeNettyChannel(), newSubEvent.getSubscriber(),
- newSubEvent.getConnection(), true);
+ newConnectionInputSubscriber(channel, newSubEvent.getSubscriber(),
+ true);
}
- private void newConnectionSubscriber(ConnectionSubscriberEvent<R, W> event) {
- if (null == newConnectionSub) {
- newConnectionSub = event.getSubscriber();
+ private void newConnectionSubscriber(ChannelSubscriberEvent<R, W> event) {
+ if (null == newChannelSub) {
+ newChannelSub = event.getSubscriber();
} else {
event.getSubscriber().onError(ONLY_ONE_CONN_SUB_ALLOWED);
}
@@ -117,7 +117,7 @@ public boolean acceptOutboundMessage(Object msg) throws Exception {
}
@Override
- public abstract Observable<RR> getInput();
+ public abstract ContentSource<RR> getInput();
@Override
public Observable<Void> write(Observable<WW> msgs) {
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2015 Netflix, Inc.
+ *
+ * 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.reactivex.netty.channel;
+
+import io.netty.channel.Channel;
+import rx.Subscriber;
+
+/**
+ * An event to communicate the subscriber of a new channel created by {@link AbstractConnectionToChannelBridge}.
+ *
+ * <h2>Connection reuse</h2>
+ *
+ * For cases, where the {@link Connection} is pooled, reuse should be indicated explicitly via
+ * {@link ConnectionInputSubscriberResetEvent}. There can be multiple {@link ConnectionInputSubscriberResetEvent}s
+ * sent to the same channel and hence the same instance of {@link AbstractConnectionToChannelBridge}.
+ *
+ * @param <R> Type read from the connection held by the event.
+ * @param <W> Type written to the connection held by the event.
+ */
+public class ChannelSubscriberEvent<R, W> {
+
+ private final Subscriber<? super Channel> subscriber;
+
+ public ChannelSubscriberEvent(Subscriber<? super Channel> subscriber) {
+ this.subscriber = subscriber;
+ }
+
+ public Subscriber<? super Channel> getSubscriber() {
+ return subscriber;
+ }
+}
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 Netflix, Inc.
+ * Copyright 2016 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
+import io.netty.util.AttributeKey;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.concurrent.EventExecutorGroup;
import rx.Observable;
@@ -44,6 +45,8 @@
*/
public abstract class Connection<R, W> implements ChannelOperations<W> {
+ public static final AttributeKey<Connection> CONNECTION_ATTRIBUTE_KEY = AttributeKey.valueOf("rx-netty-conn-attr");
+
private final Channel nettyChannel;
protected final MarkAwarePipeline markAwarePipeline;
@@ -74,7 +77,7 @@ protected Connection(Connection<R, W> toCopy) {
return new ContentSource<>(nettyChannel, new Func1<Subscriber<? super R>, Object>() {
@Override
public Object call(Subscriber<? super R> subscriber) {
- return new ConnectionInputSubscriberEvent<>(subscriber, Connection.this);
+ return new ConnectionInputSubscriberEvent<>(subscriber);
}
});
}
@@ -278,11 +281,13 @@ public Channel unsafeNettyChannel() {
* constructed completely. IOW, "this" escapes from the constructor if the listener is added in the constructor.
*/
protected void connectCloseToChannelClose() {
- nettyChannel.closeFuture().addListener(new ChannelFutureListener() {
- @Override
- public void operationComplete(ChannelFuture future) throws Exception {
- close(false); // Close this connection when the channel is closed.
- }
- });
+ nettyChannel.closeFuture()
+ .addListener(new ChannelFutureListener() {
+ @Override
+ public void operationComplete(ChannelFuture future) throws Exception {
+ close(false); // Close this connection when the channel is closed.
+ }
+ });
+ nettyChannel.attr(CONNECTION_ATTRIBUTE_KEY).set(this);
}
}
@@ -21,7 +21,7 @@
/**
* An event to indicate to {@link AbstractConnectionToChannelBridge} that the subscriber as published by
- * {@link ConnectionSubscriberEvent} should be informed of a connection creation failure, instead of a new connection.
+ * {@link ChannelSubscriberEvent} should be informed of a connection creation failure, instead of a new connection.
*
* <h2>Why do we need this?</h2>
*
@@ -22,6 +22,7 @@
import io.netty.channel.FileRegion;
import io.netty.util.concurrent.EventExecutorGroup;
import io.reactivex.netty.channel.events.ConnectionEventListener;
+import io.reactivex.netty.events.EventAttributeKeys;
import io.reactivex.netty.events.EventPublisher;
import rx.Observable;
import rx.functions.Action1;
@@ -132,9 +133,21 @@ public void closeNow() {
return delegate.closeListener();
}
- public static <R, W> ConnectionImpl<R, W> create(Channel nettyChannel, ConnectionEventListener eventListener,
- EventPublisher eventPublisher) {
- final ConnectionImpl<R, W> toReturn = new ConnectionImpl<>(nettyChannel, eventListener, eventPublisher);
+ public static <R, W> ConnectionImpl<R, W> fromChannel(Channel nettyChannel) {
+ EventPublisher ep = nettyChannel.attr(EventAttributeKeys.EVENT_PUBLISHER).get();
+ if (null == ep) {
+ throw new IllegalArgumentException("No event publisher set in the channel.");
+ }
+
+ ConnectionEventListener l = null;
+ if (ep.publishingEnabled()) {
+ l = nettyChannel.attr(EventAttributeKeys.CONNECTION_EVENT_LISTENER).get();
+ if (null == l) {
+ throw new IllegalArgumentException("No event listener set in the channel.");
+ }
+ }
+
+ final ConnectionImpl<R, W> toReturn = new ConnectionImpl<>(nettyChannel, l, ep);
toReturn.connectCloseToChannelClose();
return toReturn;
}
@@ -36,28 +36,19 @@
public final class ConnectionInputSubscriberEvent<R, W> {
private final Subscriber<? super R> subscriber;
- private final Connection<R, W> connection;
- public ConnectionInputSubscriberEvent(Subscriber<? super R> subscriber, final Connection<R, W> connection) {
+ public ConnectionInputSubscriberEvent(Subscriber<? super R> subscriber) {
if (null == subscriber) {
throw new NullPointerException("Subscriber can not be null");
}
- if (null == connection) {
- throw new NullPointerException("Connection can not be null");
- }
this.subscriber = subscriber;
- this.connection = connection;
}
public Subscriber<? super R> getSubscriber() {
return subscriber;
}
- public Connection<R, W> getConnection() {
- return connection;
- }
-
- public static <II, OO> ConnectionInputSubscriberEvent<II, OO> discardAllInput(Connection<II, OO> connection) {
+ public static <II, OO> ConnectionInputSubscriberEvent<II, OO> discardAllInput() {
return new ConnectionInputSubscriberEvent<>(Subscribers.create(new Action1<II>() {
@Override
public void call(II msg) {
@@ -68,6 +59,6 @@ public void call(II msg) {
public void call(Throwable throwable) {
// Empty as we are discarding input anyways.
}
- }), connection);
+ }));
}
}
Oops, something went wrong.

0 comments on commit 3d25c1e

Please sign in to comment.