From 2ae0d1b80a821a3cb7dd2972d362cc3dee4780bf Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Fri, 26 Oct 2018 08:42:49 -0600 Subject: [PATCH] Remove nio transport from 6.x (#34756) (#34879) This commit removes the nio transport work from 6.x This work will never be enabled outside of the test framework. Additionally, we get sufficient testing on master/7.0 right now. So there is no need to have it on 6.x. This is motivated by the fact that this work has diverged significantly from master. This makes backports difficult. Additionally, the nio transport uses many connections increasing the timeouts due to resource exhaustion in the build. --- .../smoketest/ESSmokeClientTestCase.java | 14 +- .../elasticsearch/http/HttpSmokeTestCase.java | 3 - .../org/elasticsearch/test/ESTestCase.java | 14 +- .../test/ExternalTestCluster.java | 8 +- .../transport/MockTransportClient.java | 9 - .../transport/nio/AcceptingSelector.java | 101 ------ .../transport/nio/AcceptorEventHandler.java | 87 ----- .../transport/nio/ESSelector.java | 243 ------------- .../transport/nio/EventHandler.java | 101 ------ .../transport/nio/InboundChannelBuffer.java | 245 ------------- .../elasticsearch/transport/nio/NioGroup.java | 129 ------- .../transport/nio/NioTransport.java | 172 --------- .../transport/nio/NioTransportPlugin.java | 57 --- .../transport/nio/RoundRobinSupplier.java | 39 --- .../transport/nio/SocketEventHandler.java | 163 --------- .../transport/nio/SocketSelector.java | 230 ------------ .../transport/nio/TcpReadHandler.java | 49 --- .../transport/nio/WriteOperation.java | 115 ------ .../nio/channel/AbstractNioChannel.java | 153 -------- .../transport/nio/channel/ChannelFactory.java | 206 ----------- .../transport/nio/channel/NioChannel.java | 57 --- .../nio/channel/NioServerSocketChannel.java | 63 ---- .../nio/channel/NioSocketChannel.java | 185 ---------- .../transport/nio/channel/ReadContext.java | 31 -- .../nio/channel/SelectionKeyUtils.java | 53 --- .../nio/channel/TcpChannelFactory.java | 66 ---- .../nio/channel/TcpFrameDecoder.java | 118 ------- .../channel/TcpNioServerSocketChannel.java | 57 --- .../nio/channel/TcpNioSocketChannel.java | 55 --- .../transport/nio/channel/TcpReadContext.java | 95 ----- .../nio/channel/TcpWriteContext.java | 113 ------ .../transport/nio/channel/WriteContext.java | 40 --- .../transport/nio/AcceptingSelectorTests.java | 128 ------- .../nio/AcceptorEventHandlerTests.java | 96 ----- .../transport/nio/ESSelectorTests.java | 112 ------ .../nio/InboundChannelBufferTests.java | 210 ----------- .../transport/nio/NioGroupTests.java | 82 ----- .../nio/SimpleNioTransportTests.java | 142 -------- .../nio/SocketEventHandlerTests.java | 169 --------- .../transport/nio/SocketSelectorTests.java | 330 ------------------ .../nio/TestingSocketEventHandler.java | 68 ---- .../transport/nio/WriteOperationTests.java | 119 ------- .../nio/channel/ChannelFactoryTests.java | 153 -------- .../nio/channel/DoNotRegisterChannel.java | 39 --- .../channel/DoNotRegisterServerChannel.java | 40 --- .../channel/NioServerSocketChannelTests.java | 108 ------ .../nio/channel/NioSocketChannelTests.java | 145 -------- .../nio/channel/TcpFrameDecoderTests.java | 167 --------- .../nio/channel/TcpReadContextTests.java | 159 --------- .../nio/channel/TcpWriteContextTests.java | 213 ----------- .../transport/nio/utils/TestSelectionKey.java | 65 ---- 51 files changed, 8 insertions(+), 5608 deletions(-) delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/AcceptingSelector.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/AcceptorEventHandler.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/ESSelector.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/EventHandler.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/InboundChannelBuffer.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/NioGroup.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/NioTransport.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/NioTransportPlugin.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/RoundRobinSupplier.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/SocketEventHandler.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/SocketSelector.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/TcpReadHandler.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/WriteOperation.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/channel/AbstractNioChannel.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/channel/ChannelFactory.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/channel/NioChannel.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/channel/NioServerSocketChannel.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/channel/NioSocketChannel.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/channel/ReadContext.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/channel/SelectionKeyUtils.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpChannelFactory.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpFrameDecoder.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpNioServerSocketChannel.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpNioSocketChannel.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpReadContext.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpWriteContext.java delete mode 100644 test/framework/src/main/java/org/elasticsearch/transport/nio/channel/WriteContext.java delete mode 100644 test/framework/src/test/java/org/elasticsearch/transport/nio/AcceptingSelectorTests.java delete mode 100644 test/framework/src/test/java/org/elasticsearch/transport/nio/AcceptorEventHandlerTests.java delete mode 100644 test/framework/src/test/java/org/elasticsearch/transport/nio/ESSelectorTests.java delete mode 100644 test/framework/src/test/java/org/elasticsearch/transport/nio/InboundChannelBufferTests.java delete mode 100644 test/framework/src/test/java/org/elasticsearch/transport/nio/NioGroupTests.java delete mode 100644 test/framework/src/test/java/org/elasticsearch/transport/nio/SimpleNioTransportTests.java delete mode 100644 test/framework/src/test/java/org/elasticsearch/transport/nio/SocketEventHandlerTests.java delete mode 100644 test/framework/src/test/java/org/elasticsearch/transport/nio/SocketSelectorTests.java delete mode 100644 test/framework/src/test/java/org/elasticsearch/transport/nio/TestingSocketEventHandler.java delete mode 100644 test/framework/src/test/java/org/elasticsearch/transport/nio/WriteOperationTests.java delete mode 100644 test/framework/src/test/java/org/elasticsearch/transport/nio/channel/ChannelFactoryTests.java delete mode 100644 test/framework/src/test/java/org/elasticsearch/transport/nio/channel/DoNotRegisterChannel.java delete mode 100644 test/framework/src/test/java/org/elasticsearch/transport/nio/channel/DoNotRegisterServerChannel.java delete mode 100644 test/framework/src/test/java/org/elasticsearch/transport/nio/channel/NioServerSocketChannelTests.java delete mode 100644 test/framework/src/test/java/org/elasticsearch/transport/nio/channel/NioSocketChannelTests.java delete mode 100644 test/framework/src/test/java/org/elasticsearch/transport/nio/channel/TcpFrameDecoderTests.java delete mode 100644 test/framework/src/test/java/org/elasticsearch/transport/nio/channel/TcpReadContextTests.java delete mode 100644 test/framework/src/test/java/org/elasticsearch/transport/nio/channel/TcpWriteContextTests.java delete mode 100644 test/framework/src/test/java/org/elasticsearch/transport/nio/utils/TestSelectionKey.java diff --git a/qa/smoke-test-client/src/test/java/org/elasticsearch/smoketest/ESSmokeClientTestCase.java b/qa/smoke-test-client/src/test/java/org/elasticsearch/smoketest/ESSmokeClientTestCase.java index 908e8e1c71114..8ad8605554f39 100644 --- a/qa/smoke-test-client/src/test/java/org/elasticsearch/smoketest/ESSmokeClientTestCase.java +++ b/qa/smoke-test-client/src/test/java/org/elasticsearch/smoketest/ESSmokeClientTestCase.java @@ -32,7 +32,6 @@ import org.elasticsearch.plugins.Plugin; import org.elasticsearch.transport.MockTcpTransportPlugin; import org.elasticsearch.transport.client.PreBuiltTransportClient; -import org.elasticsearch.transport.nio.NioTransportPlugin; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; @@ -82,16 +81,9 @@ private static Client startClient(Path tempDir, TransportAddress... transportAdd .put("client.transport.ignore_cluster_name", true) .put(Environment.PATH_HOME_SETTING.getKey(), tempDir); final Collection> plugins; - boolean usNio = random().nextBoolean(); - String transportKey; - Class transportPlugin; - if (usNio) { - transportKey = NioTransportPlugin.NIO_TRANSPORT_NAME; - transportPlugin = NioTransportPlugin.class; - } else { - transportKey = MockTcpTransportPlugin.MOCK_TCP_TRANSPORT_NAME; - transportPlugin = MockTcpTransportPlugin.class; - } + String transportKey = MockTcpTransportPlugin.MOCK_TCP_TRANSPORT_NAME; + Class transportPlugin = MockTcpTransportPlugin.class; + if (random().nextBoolean()) { builder.put(NetworkModule.TRANSPORT_TYPE_KEY, transportKey); plugins = Collections.singleton(transportPlugin); diff --git a/qa/smoke-test-http/src/test/java/org/elasticsearch/http/HttpSmokeTestCase.java b/qa/smoke-test-http/src/test/java/org/elasticsearch/http/HttpSmokeTestCase.java index bb13d486a9adc..f01c523e86273 100644 --- a/qa/smoke-test-http/src/test/java/org/elasticsearch/http/HttpSmokeTestCase.java +++ b/qa/smoke-test-http/src/test/java/org/elasticsearch/http/HttpSmokeTestCase.java @@ -24,7 +24,6 @@ import org.elasticsearch.test.ESIntegTestCase; import org.elasticsearch.transport.MockTcpTransportPlugin; import org.elasticsearch.transport.Netty4Plugin; -import org.elasticsearch.transport.nio.NioTransportPlugin; import org.junit.BeforeClass; import java.util.Arrays; @@ -47,8 +46,6 @@ public static void setUpTransport() { private static String getTypeKey(Class clazz) { if (clazz.equals(MockTcpTransportPlugin.class)) { return MockTcpTransportPlugin.MOCK_TCP_TRANSPORT_NAME; - } else if (clazz.equals(NioTransportPlugin.class)) { - return NioTransportPlugin.NIO_TRANSPORT_NAME; } else { assert clazz.equals(Netty4Plugin.class); return Netty4Plugin.NETTY_TRANSPORT_NAME; diff --git a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java index ec6d8731b94a9..88e7fb1144c92 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java @@ -112,7 +112,6 @@ import org.elasticsearch.test.junit.listeners.ReproduceInfoPrinter; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.MockTcpTransportPlugin; -import org.elasticsearch.transport.nio.NioTransportPlugin; import org.joda.time.DateTimeZone; import org.junit.After; import org.junit.AfterClass; @@ -128,8 +127,8 @@ import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; -import java.time.ZoneId; import java.security.Security; +import java.time.ZoneId; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -991,19 +990,12 @@ public static String randomGeohash(int minPrecision, int maxPrecision) { return geohashGenerator.ofStringLength(random(), minPrecision, maxPrecision); } - private static boolean useNio; - - @BeforeClass - public static void setUseNio() throws Exception { - useNio = randomBoolean(); - } - public static String getTestTransportType() { - return useNio ? NioTransportPlugin.NIO_TRANSPORT_NAME : MockTcpTransportPlugin.MOCK_TCP_TRANSPORT_NAME; + return MockTcpTransportPlugin.MOCK_TCP_TRANSPORT_NAME; } public static Class getTestTransportPlugin() { - return useNio ? NioTransportPlugin.class : MockTcpTransportPlugin.class; + return MockTcpTransportPlugin.class; } private static final GeohashGenerator geohashGenerator = new GeohashGenerator(); diff --git a/test/framework/src/main/java/org/elasticsearch/test/ExternalTestCluster.java b/test/framework/src/main/java/org/elasticsearch/test/ExternalTestCluster.java index 12375e66b297f..a9cc49f11386b 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/ExternalTestCluster.java +++ b/test/framework/src/main/java/org/elasticsearch/test/ExternalTestCluster.java @@ -36,7 +36,6 @@ import org.elasticsearch.plugins.Plugin; import org.elasticsearch.transport.MockTcpTransportPlugin; import org.elasticsearch.transport.MockTransportClient; -import org.elasticsearch.transport.nio.NioTransportPlugin; import java.io.IOException; import java.net.InetSocketAddress; @@ -84,12 +83,9 @@ public ExternalTestCluster(Path tempDir, Settings additionalSettings, Collection if (addMockTcpTransport) { String transport = getTestTransportType(); clientSettingsBuilder.put(NetworkModule.TRANSPORT_TYPE_KEY, transport); - if (pluginClasses.contains(MockTcpTransportPlugin.class) == false && - pluginClasses.contains(NioTransportPlugin.class) == false) { + if (pluginClasses.contains(MockTcpTransportPlugin.class) == false) { pluginClasses = new ArrayList<>(pluginClasses); - if (transport.equals(NioTransportPlugin.NIO_TRANSPORT_NAME)) { - pluginClasses.add(NioTransportPlugin.class); - } else { + if (transport.equals(MockTcpTransportPlugin.MOCK_TCP_TRANSPORT_NAME)) { pluginClasses.add(MockTcpTransportPlugin.class); } } diff --git a/test/framework/src/main/java/org/elasticsearch/transport/MockTransportClient.java b/test/framework/src/main/java/org/elasticsearch/transport/MockTransportClient.java index 027b26e32d736..05723573c1b0b 100644 --- a/test/framework/src/main/java/org/elasticsearch/transport/MockTransportClient.java +++ b/test/framework/src/main/java/org/elasticsearch/transport/MockTransportClient.java @@ -23,7 +23,6 @@ import org.elasticsearch.common.network.NetworkModule; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.transport.nio.NioTransportPlugin; import java.util.ArrayList; import java.util.Arrays; @@ -59,14 +58,6 @@ private static Collection> addMockTransportIfMissing(Set plugins.add(MockTcpTransportPlugin.class); return plugins; } - } else if (NioTransportPlugin.NIO_TRANSPORT_NAME.equals(transportType)) { - if (plugins.contains(NioTransportPlugin.class)) { - return plugins; - } else { - plugins = new ArrayList<>(plugins); - plugins.add(NioTransportPlugin.class); - return plugins; - } } return plugins; } diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/AcceptingSelector.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/AcceptingSelector.java deleted file mode 100644 index 23775b4bc1665..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/AcceptingSelector.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.elasticsearch.transport.nio.channel.NioServerSocketChannel; - -import java.io.IOException; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.util.concurrent.ConcurrentLinkedQueue; - -/** - * Selector implementation that handles {@link NioServerSocketChannel}. It's main piece of functionality is - * accepting new channels. - */ -public class AcceptingSelector extends ESSelector { - - private final AcceptorEventHandler eventHandler; - private final ConcurrentLinkedQueue newChannels = new ConcurrentLinkedQueue<>(); - - public AcceptingSelector(AcceptorEventHandler eventHandler) throws IOException { - super(eventHandler); - this.eventHandler = eventHandler; - } - - public AcceptingSelector(AcceptorEventHandler eventHandler, Selector selector) throws IOException { - super(eventHandler, selector); - this.eventHandler = eventHandler; - } - - @Override - void processKey(SelectionKey selectionKey) { - NioServerSocketChannel serverChannel = (NioServerSocketChannel) selectionKey.attachment(); - if (selectionKey.isAcceptable()) { - try { - eventHandler.acceptChannel(serverChannel); - } catch (IOException e) { - eventHandler.acceptException(serverChannel, e); - } - } - } - - @Override - void preSelect() { - setUpNewServerChannels(); - } - - @Override - void cleanup() { - channelsToClose.addAll(newChannels); - } - - /** - * Schedules a NioServerSocketChannel to be registered with this selector. The channel will by queued and - * eventually registered next time through the event loop. - * - * @param serverSocketChannel the channel to register - */ - public void scheduleForRegistration(NioServerSocketChannel serverSocketChannel) { - newChannels.add(serverSocketChannel); - ensureSelectorOpenForEnqueuing(newChannels, serverSocketChannel); - wakeup(); - } - - private void setUpNewServerChannels() { - NioServerSocketChannel newChannel; - while ((newChannel = this.newChannels.poll()) != null) { - assert newChannel.getSelector() == this : "The channel must be registered with the selector with which it was created"; - try { - if (newChannel.isOpen()) { - newChannel.register(); - SelectionKey selectionKey = newChannel.getSelectionKey(); - selectionKey.attach(newChannel); - eventHandler.serverChannelRegistered(newChannel); - } else { - eventHandler.registrationException(newChannel, new ClosedChannelException()); - } - } catch (IOException e) { - eventHandler.registrationException(newChannel, e); - } - } - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/AcceptorEventHandler.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/AcceptorEventHandler.java deleted file mode 100644 index ba0fa9356b9eb..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/AcceptorEventHandler.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.message.ParameterizedMessage; -import org.elasticsearch.transport.nio.channel.ChannelFactory; -import org.elasticsearch.transport.nio.channel.NioServerSocketChannel; -import org.elasticsearch.transport.nio.channel.NioSocketChannel; -import org.elasticsearch.transport.nio.channel.SelectionKeyUtils; - -import java.io.IOException; -import java.util.function.Supplier; - -/** - * Event handler designed to handle events from server sockets - */ -public class AcceptorEventHandler extends EventHandler { - - private final Supplier selectorSupplier; - - public AcceptorEventHandler(Logger logger, Supplier selectorSupplier) { - super(logger); - this.selectorSupplier = selectorSupplier; - } - - /** - * This method is called when a NioServerSocketChannel is successfully registered. It should only be - * called once per channel. - * - * @param nioServerSocketChannel that was registered - */ - void serverChannelRegistered(NioServerSocketChannel nioServerSocketChannel) { - SelectionKeyUtils.setAcceptInterested(nioServerSocketChannel); - } - - /** - * This method is called when an attempt to register a server channel throws an exception. - * - * @param channel that was registered - * @param exception that occurred - */ - void registrationException(NioServerSocketChannel channel, Exception exception) { - logger.error(new ParameterizedMessage("failed to register server channel: {}", channel), exception); - } - - /** - * This method is called when a server channel signals it is ready to accept a connection. All of the - * accept logic should occur in this call. - * - * @param nioServerChannel that can accept a connection - */ - void acceptChannel(NioServerSocketChannel nioServerChannel) throws IOException { - ChannelFactory channelFactory = nioServerChannel.getChannelFactory(); - SocketSelector selector = selectorSupplier.get(); - NioSocketChannel nioSocketChannel = channelFactory.acceptNioChannel(nioServerChannel, selector); - nioServerChannel.getAcceptContext().accept(nioSocketChannel); - } - - /** - * This method is called when an attempt to accept a connection throws an exception. - * - * @param nioServerChannel that accepting a connection - * @param exception that occurred - */ - void acceptException(NioServerSocketChannel nioServerChannel, Exception exception) { - logger.debug(() -> new ParameterizedMessage("exception while accepting new channel from server channel: {}", - nioServerChannel), exception); - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/ESSelector.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/ESSelector.java deleted file mode 100644 index 91e308a33b5ff..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/ESSelector.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.elasticsearch.action.support.PlainActionFuture; -import org.elasticsearch.transport.nio.channel.NioChannel; - -import java.io.Closeable; -import java.io.IOException; -import java.nio.channels.CancelledKeyException; -import java.nio.channels.ClosedSelectorException; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.util.Iterator; -import java.util.Set; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.locks.ReentrantLock; -import java.util.stream.Collectors; - -/** - * This is a basic selector abstraction used by {@link org.elasticsearch.transport.nio.NioTransport}. This - * selector wraps a raw nio {@link Selector}. When you call {@link #runLoop()}, the selector will run until - * {@link #close()} is called. This instance handles closing of channels. Users should call - * {@link #queueChannelClose(NioChannel)} to schedule a channel for close by this selector. - *

- * Children of this class should implement the specific {@link #processKey(SelectionKey)}, - * {@link #preSelect()}, and {@link #cleanup()} functionality. - */ -public abstract class ESSelector implements Closeable { - - final Selector selector; - final ConcurrentLinkedQueue channelsToClose = new ConcurrentLinkedQueue<>(); - - private final EventHandler eventHandler; - private final ReentrantLock runLock = new ReentrantLock(); - private final CountDownLatch exitedLoop = new CountDownLatch(1); - private final AtomicBoolean isClosed = new AtomicBoolean(false); - private final PlainActionFuture isRunningFuture = PlainActionFuture.newFuture(); - private volatile Thread thread; - - ESSelector(EventHandler eventHandler) throws IOException { - this(eventHandler, Selector.open()); - } - - ESSelector(EventHandler eventHandler, Selector selector) throws IOException { - this.eventHandler = eventHandler; - this.selector = selector; - } - - /** - * Starts this selector. The selector will run until {@link #close()} is called. - */ - public void runLoop() { - if (runLock.tryLock()) { - isRunningFuture.onResponse(true); - try { - setThread(); - while (isOpen()) { - singleLoop(); - } - } finally { - try { - cleanupAndCloseChannels(); - } finally { - try { - selector.close(); - } catch (IOException e) { - eventHandler.closeSelectorException(e); - } finally { - runLock.unlock(); - exitedLoop.countDown(); - } - } - } - } else { - throw new IllegalStateException("selector is already running"); - } - } - - void singleLoop() { - try { - closePendingChannels(); - preSelect(); - - int ready = selector.select(300); - if (ready > 0) { - Set selectionKeys = selector.selectedKeys(); - Iterator keyIterator = selectionKeys.iterator(); - while (keyIterator.hasNext()) { - SelectionKey sk = keyIterator.next(); - keyIterator.remove(); - if (sk.isValid()) { - try { - processKey(sk); - } catch (CancelledKeyException cke) { - eventHandler.genericChannelException((NioChannel) sk.attachment(), cke); - } - } else { - eventHandler.genericChannelException((NioChannel) sk.attachment(), new CancelledKeyException()); - } - } - } - } catch (ClosedSelectorException e) { - if (isOpen()) { - throw e; - } - } catch (IOException e) { - eventHandler.selectException(e); - } catch (Exception e) { - eventHandler.uncaughtException(e); - } - } - - void cleanupAndCloseChannels() { - cleanup(); - channelsToClose.addAll(selector.keys().stream().map(sk -> (NioChannel) sk.attachment()).collect(Collectors.toList())); - closePendingChannels(); - } - - /** - * Called by the base {@link ESSelector} class when there is a {@link SelectionKey} to be handled. - * - * @param selectionKey the key to be handled - * @throws CancelledKeyException thrown when the key has already been cancelled - */ - abstract void processKey(SelectionKey selectionKey) throws CancelledKeyException; - - /** - * Called immediately prior to a raw {@link Selector#select()} call. Should be used to implement - * channel registration, handling queued writes, and other work that is not specifically processing - * a selection key. - */ - abstract void preSelect(); - - /** - * Called once as the selector is being closed. - */ - abstract void cleanup(); - - void setThread() { - thread = Thread.currentThread(); - } - - public boolean isOnCurrentThread() { - return Thread.currentThread() == thread; - } - - void wakeup() { - // TODO: Do we need the wakeup optimizations that some other libraries use? - selector.wakeup(); - } - - @Override - public void close() throws IOException { - if (isClosed.compareAndSet(false, true)) { - wakeup(); - if (isRunning()) { - try { - exitedLoop.await(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new IllegalStateException("Thread was interrupted while waiting for selector to close", e); - } - } else if (selector.isOpen()) { - selector.close(); - } - } - } - - public void queueChannelClose(NioChannel channel) { - assert channel.getSelector() == this : "Must schedule a channel for closure with its selector"; - channelsToClose.offer(channel); - ensureSelectorOpenForEnqueuing(channelsToClose, channel); - wakeup(); - } - - public Selector rawSelector() { - return selector; - } - - public boolean isOpen() { - return isClosed.get() == false; - } - - public boolean isRunning() { - return runLock.isLocked(); - } - - public PlainActionFuture isRunningFuture() { - return isRunningFuture; - } - - /** - * This is a convenience method to be called after some object (normally channels) are enqueued with this - * selector. This method will check if the selector is still open. If it is open, normal operation can - * proceed. - * - * If the selector is closed, then we attempt to remove the object from the queue. If the removal - * succeeds then we throw an {@link IllegalStateException} indicating that normal operation failed. If - * the object cannot be removed from the queue, then the object has already been handled by the selector - * and operation can proceed normally. - * - * If this method is called from the selector thread, we will not throw an exception as the selector - * thread can manipulate its queues internally even if it is no longer open. - * - * @param queue the queue to which the object was added - * @param objectAdded the objected added - * @param the object type - */ - void ensureSelectorOpenForEnqueuing(ConcurrentLinkedQueue queue, O objectAdded) { - if (isOpen() == false && isOnCurrentThread() == false) { - if (queue.remove(objectAdded)) { - throw new IllegalStateException("selector is already closed"); - } - } - } - - private void closePendingChannels() { - NioChannel channel; - while ((channel = channelsToClose.poll()) != null) { - eventHandler.handleClose(channel); - } - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/EventHandler.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/EventHandler.java deleted file mode 100644 index 8521f71616266..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/EventHandler.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.message.ParameterizedMessage; -import org.elasticsearch.transport.nio.channel.NioChannel; - -import java.io.IOException; -import java.nio.channels.Selector; - -public abstract class EventHandler { - - protected final Logger logger; - - public EventHandler(Logger logger) { - this.logger = logger; - } - - /** - * This method handles an IOException that was thrown during a call to {@link Selector#select(long)}. - * - * @param exception the exception - */ - void selectException(IOException exception) { - logger.warn(new ParameterizedMessage("io exception during select [thread={}]", Thread.currentThread().getName()), exception); - } - - /** - * This method handles an IOException that was thrown during a call to {@link Selector#close()}. - * - * @param exception the exception - */ - void closeSelectorException(IOException exception) { - logger.warn(new ParameterizedMessage("io exception while closing selector [thread={}]", Thread.currentThread().getName()), - exception); - } - - /** - * This method handles an exception that was uncaught during a select loop. - * - * @param exception that was uncaught - */ - void uncaughtException(Exception exception) { - Thread thread = Thread.currentThread(); - thread.getUncaughtExceptionHandler().uncaughtException(thread, exception); - } - - /** - * This method handles the closing of an NioChannel - * - * @param channel that should be closed - */ - void handleClose(NioChannel channel) { - try { - channel.closeFromSelector(); - } catch (IOException e) { - closeException(channel, e); - } - assert channel.isOpen() == false : "Should always be done as we are on the selector thread"; - } - - /** - * This method is called when an attempt to close a channel throws an exception. - * - * @param channel that was being closed - * @param exception that occurred - */ - void closeException(NioChannel channel, Exception exception) { - logger.debug(() -> new ParameterizedMessage("exception while closing channel: {}", channel), exception); - } - - /** - * This method is called when handling an event from a channel fails due to an unexpected exception. - * An example would be if checking ready ops on a {@link java.nio.channels.SelectionKey} threw - * {@link java.nio.channels.CancelledKeyException}. - * - * @param channel that caused the exception - * @param exception that was thrown - */ - void genericChannelException(NioChannel channel, Exception exception) { - logger.debug(() -> new ParameterizedMessage("exception while handling event for channel: {}", channel), exception); - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/InboundChannelBuffer.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/InboundChannelBuffer.java deleted file mode 100644 index 11d340a30a0c8..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/InboundChannelBuffer.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.elasticsearch.ExceptionsHelper; -import org.elasticsearch.common.lease.Releasable; -import org.elasticsearch.common.util.BigArrays; - -import java.nio.ByteBuffer; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Supplier; - -/** - * This is a channel byte buffer composed internally of 16kb pages. When an entire message has been read - * and consumed, the {@link #release(long)} method releases the bytes from the head of the buffer and closes - * the pages internally. If more space is needed at the end of the buffer {@link #ensureCapacity(long)} can - * be called and the buffer will expand using the supplier provided. - */ -public final class InboundChannelBuffer implements Releasable { - - private static final int PAGE_SIZE = BigArrays.BYTE_PAGE_SIZE; - private static final int PAGE_MASK = PAGE_SIZE - 1; - private static final int PAGE_SHIFT = Integer.numberOfTrailingZeros(PAGE_SIZE); - private static final ByteBuffer[] EMPTY_BYTE_BUFFER_ARRAY = new ByteBuffer[0]; - - - private final ArrayDeque pages; - private final Supplier pageSupplier; - private final AtomicBoolean isClosed = new AtomicBoolean(false); - - private long capacity = 0; - private long internalIndex = 0; - // The offset is an int as it is the offset of where the bytes begin in the first buffer - private int offset = 0; - - public InboundChannelBuffer(Supplier pageSupplier) { - this.pageSupplier = pageSupplier; - this.pages = new ArrayDeque<>(); - this.capacity = PAGE_SIZE * pages.size(); - ensureCapacity(PAGE_SIZE); - } - - @Override - public void close() { - if (isClosed.compareAndSet(false, true)) { - Page page; - List closingExceptions = new ArrayList<>(); - while ((page = pages.pollFirst()) != null) { - try { - page.close(); - } catch (RuntimeException e) { - closingExceptions.add(e); - } - } - ExceptionsHelper.rethrowAndSuppress(closingExceptions); - } - } - - public void ensureCapacity(long requiredCapacity) { - if (isClosed.get()) { - throw new IllegalStateException("Cannot allocate new pages if the buffer is closed."); - } - if (capacity < requiredCapacity) { - int numPages = numPages(requiredCapacity + offset); - int pagesToAdd = numPages - pages.size(); - for (int i = 0; i < pagesToAdd; i++) { - Page page = pageSupplier.get(); - pages.addLast(page); - } - capacity += pagesToAdd * PAGE_SIZE; - } - } - - /** - * This method will release bytes from the head of this buffer. If you release bytes past the current - * index the index is truncated to zero. - * - * @param bytesToRelease number of bytes to drop - */ - public void release(long bytesToRelease) { - if (bytesToRelease > capacity) { - throw new IllegalArgumentException("Releasing more bytes [" + bytesToRelease + "] than buffer capacity [" + capacity + "]."); - } - - int pagesToRelease = pageIndex(offset + bytesToRelease); - for (int i = 0; i < pagesToRelease; i++) { - pages.removeFirst().close(); - } - capacity -= bytesToRelease; - internalIndex = Math.max(internalIndex - bytesToRelease, 0); - offset = indexInPage(bytesToRelease + offset); - } - - /** - * This method will return an array of {@link ByteBuffer} representing the bytes from the beginning of - * this buffer up through the index argument that was passed. The buffers will be duplicates of the - * internal buffers, so any modifications to the markers {@link ByteBuffer#position()}, - * {@link ByteBuffer#limit()}, etc will not modify the this class. - * - * @param to the index to slice up to - * @return the byte buffers - */ - public ByteBuffer[] sliceBuffersTo(long to) { - if (to > capacity) { - throw new IndexOutOfBoundsException("can't slice a channel buffer with capacity [" + capacity + - "], with slice parameters to [" + to + "]"); - } else if (to == 0) { - return EMPTY_BYTE_BUFFER_ARRAY; - } - long indexWithOffset = to + offset; - int pageCount = pageIndex(indexWithOffset); - int finalLimit = indexInPage(indexWithOffset); - if (finalLimit != 0) { - pageCount += 1; - } - - ByteBuffer[] buffers = new ByteBuffer[pageCount]; - Iterator pageIterator = pages.iterator(); - ByteBuffer firstBuffer = pageIterator.next().byteBuffer.duplicate(); - firstBuffer.position(firstBuffer.position() + offset); - buffers[0] = firstBuffer; - for (int i = 1; i < buffers.length; i++) { - buffers[i] = pageIterator.next().byteBuffer.duplicate(); - } - if (finalLimit != 0) { - buffers[buffers.length - 1].limit(finalLimit); - } - - return buffers; - } - - /** - * This method will return an array of {@link ByteBuffer} representing the bytes from the index passed - * through the end of this buffer. The buffers will be duplicates of the internal buffers, so any - * modifications to the markers {@link ByteBuffer#position()}, {@link ByteBuffer#limit()}, etc will not - * modify the this class. - * - * @param from the index to slice from - * @return the byte buffers - */ - public ByteBuffer[] sliceBuffersFrom(long from) { - if (from > capacity) { - throw new IndexOutOfBoundsException("can't slice a channel buffer with capacity [" + capacity + - "], with slice parameters from [" + from + "]"); - } else if (from == capacity) { - return EMPTY_BYTE_BUFFER_ARRAY; - } - long indexWithOffset = from + offset; - - int pageIndex = pageIndex(indexWithOffset); - int indexInPage = indexInPage(indexWithOffset); - - ByteBuffer[] buffers = new ByteBuffer[pages.size() - pageIndex]; - Iterator pageIterator = pages.descendingIterator(); - for (int i = buffers.length - 1; i > 0; --i) { - buffers[i] = pageIterator.next().byteBuffer.duplicate(); - } - ByteBuffer firstPostIndexBuffer = pageIterator.next().byteBuffer.duplicate(); - firstPostIndexBuffer.position(firstPostIndexBuffer.position() + indexInPage); - buffers[0] = firstPostIndexBuffer; - - return buffers; - } - - public void incrementIndex(long delta) { - if (delta < 0) { - throw new IllegalArgumentException("Cannot increment an index with a negative delta [" + delta + "]"); - } - - long newIndex = delta + internalIndex; - if (newIndex > capacity) { - throw new IllegalArgumentException("Cannot increment an index [" + internalIndex + "] with a delta [" + delta + - "] that will result in a new index [" + newIndex + "] that is greater than the capacity [" + capacity + "]."); - } - internalIndex = newIndex; - } - - public long getIndex() { - return internalIndex; - } - - public long getCapacity() { - return capacity; - } - - public long getRemaining() { - long remaining = capacity - internalIndex; - assert remaining >= 0 : "The remaining [" + remaining + "] number of bytes should not be less than zero."; - return remaining; - } - - private int numPages(long capacity) { - final long numPages = (capacity + PAGE_MASK) >>> PAGE_SHIFT; - if (numPages > Integer.MAX_VALUE) { - throw new IllegalArgumentException("pageSize=" + (PAGE_MASK + 1) + " is too small for such as capacity: " + capacity); - } - return (int) numPages; - } - - private int pageIndex(long index) { - return (int) (index >>> PAGE_SHIFT); - } - - private int indexInPage(long index) { - return (int) (index & PAGE_MASK); - } - - public static class Page implements Releasable { - - private final ByteBuffer byteBuffer; - private final Releasable releasable; - - public Page(ByteBuffer byteBuffer, Releasable releasable) { - this.byteBuffer = byteBuffer; - this.releasable = releasable; - } - - @Override - public void close() { - releasable.close(); - } - - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/NioGroup.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/NioGroup.java deleted file mode 100644 index b0e1862c706ca..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/NioGroup.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.apache.logging.log4j.Logger; -import org.apache.lucene.util.IOUtils; -import org.elasticsearch.transport.nio.channel.ChannelFactory; -import org.elasticsearch.transport.nio.channel.NioServerSocketChannel; -import org.elasticsearch.transport.nio.channel.NioSocketChannel; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -/** - * The NioGroup is a group of selectors for interfacing with java nio. When it is started it will create the - * configured number of socket and acceptor selectors. Each selector will be running in a dedicated thread. - * Server connections can be bound using the {@link #bindServerChannel(InetSocketAddress, ChannelFactory)} - * method. Client connections can be opened using the {@link #openChannel(InetSocketAddress, ChannelFactory)} - * method. - *

- * The logic specific to a particular channel is provided by the {@link ChannelFactory} passed to the method - * when the channel is created. This is what allows an NioGroup to support different channel types. - */ -public class NioGroup implements AutoCloseable { - - - private final ArrayList acceptors; - private final RoundRobinSupplier acceptorSupplier; - - private final ArrayList socketSelectors; - private final RoundRobinSupplier socketSelectorSupplier; - - private final AtomicBoolean isOpen = new AtomicBoolean(true); - - public NioGroup(Logger logger, ThreadFactory acceptorThreadFactory, int acceptorCount, - BiFunction, AcceptorEventHandler> acceptorEventHandlerFunction, - ThreadFactory socketSelectorThreadFactory, int socketSelectorCount, - Function socketEventHandlerFunction) throws IOException { - acceptors = new ArrayList<>(acceptorCount); - socketSelectors = new ArrayList<>(socketSelectorCount); - - try { - for (int i = 0; i < socketSelectorCount; ++i) { - SocketSelector selector = new SocketSelector(socketEventHandlerFunction.apply(logger)); - socketSelectors.add(selector); - } - startSelectors(socketSelectors, socketSelectorThreadFactory); - - for (int i = 0; i < acceptorCount; ++i) { - SocketSelector[] childSelectors = this.socketSelectors.toArray(new SocketSelector[this.socketSelectors.size()]); - Supplier selectorSupplier = new RoundRobinSupplier<>(childSelectors); - AcceptingSelector acceptor = new AcceptingSelector(acceptorEventHandlerFunction.apply(logger, selectorSupplier)); - acceptors.add(acceptor); - } - startSelectors(acceptors, acceptorThreadFactory); - } catch (Exception e) { - try { - close(); - } catch (Exception e1) { - e.addSuppressed(e1); - } - throw e; - } - - socketSelectorSupplier = new RoundRobinSupplier<>(socketSelectors.toArray(new SocketSelector[socketSelectors.size()])); - acceptorSupplier = new RoundRobinSupplier<>(acceptors.toArray(new AcceptingSelector[acceptors.size()])); - } - - public S bindServerChannel(InetSocketAddress address, ChannelFactory factory) - throws IOException { - ensureOpen(); - if (acceptors.isEmpty()) { - throw new IllegalArgumentException("There are no acceptors configured. Without acceptors, server channels are not supported."); - } - return factory.openNioServerSocketChannel(address, acceptorSupplier.get()); - } - - public S openChannel(InetSocketAddress address, ChannelFactory factory) throws IOException { - ensureOpen(); - return factory.openNioChannel(address, socketSelectorSupplier.get()); - } - - @Override - public void close() throws IOException { - if (isOpen.compareAndSet(true, false)) { - IOUtils.close(Stream.concat(acceptors.stream(), socketSelectors.stream()).collect(Collectors.toList())); - } - } - - private static void startSelectors(Iterable selectors, ThreadFactory threadFactory) { - for (ESSelector acceptor : selectors) { - if (acceptor.isRunning() == false) { - threadFactory.newThread(acceptor::runLoop).start(); - acceptor.isRunningFuture().actionGet(); - } - } - } - - private void ensureOpen() { - if (isOpen.get() == false) { - throw new IllegalStateException("NioGroup is closed."); - } - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/NioTransport.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/NioTransport.java deleted file mode 100644 index bb28d93f85a84..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/NioTransport.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.apache.logging.log4j.Logger; -import org.elasticsearch.ElasticsearchException; -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.cluster.node.DiscoveryNode; -import org.elasticsearch.common.io.stream.NamedWriteableRegistry; -import org.elasticsearch.common.network.NetworkService; -import org.elasticsearch.common.recycler.Recycler; -import org.elasticsearch.common.settings.Setting; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.common.util.BigArrays; -import org.elasticsearch.common.util.PageCacheRecycler; -import org.elasticsearch.common.util.concurrent.EsExecutors; -import org.elasticsearch.indices.breaker.CircuitBreakerService; -import org.elasticsearch.threadpool.ThreadPool; -import org.elasticsearch.transport.TcpTransport; -import org.elasticsearch.transport.Transports; -import org.elasticsearch.transport.nio.channel.NioServerSocketChannel; -import org.elasticsearch.transport.nio.channel.NioSocketChannel; -import org.elasticsearch.transport.nio.channel.TcpChannelFactory; -import org.elasticsearch.transport.nio.channel.TcpNioServerSocketChannel; -import org.elasticsearch.transport.nio.channel.TcpNioSocketChannel; -import org.elasticsearch.transport.nio.channel.TcpReadContext; -import org.elasticsearch.transport.nio.channel.TcpWriteContext; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; -import java.util.concurrent.ConcurrentMap; -import java.util.function.Consumer; -import java.util.function.Supplier; - -import static org.elasticsearch.common.settings.Setting.intSetting; -import static org.elasticsearch.common.util.concurrent.ConcurrentCollections.newConcurrentMap; -import static org.elasticsearch.common.util.concurrent.EsExecutors.daemonThreadFactory; - -public class NioTransport extends TcpTransport { - - public static final String TRANSPORT_WORKER_THREAD_NAME_PREFIX = Transports.NIO_TRANSPORT_WORKER_THREAD_NAME_PREFIX; - public static final String TRANSPORT_ACCEPTOR_THREAD_NAME_PREFIX = Transports.NIO_TRANSPORT_ACCEPTOR_THREAD_NAME_PREFIX; - - public static final Setting NIO_WORKER_COUNT = - new Setting<>("transport.nio.worker_count", - (s) -> Integer.toString(EsExecutors.numberOfProcessors(s) * 2), - (s) -> Setting.parseInt(s, 1, "transport.nio.worker_count"), Setting.Property.NodeScope); - - public static final Setting NIO_ACCEPTOR_COUNT = - intSetting("transport.nio.acceptor_count", 1, 1, Setting.Property.NodeScope); - - private final PageCacheRecycler pageCacheRecycler; - private final ConcurrentMap profileToChannelFactory = newConcurrentMap(); - private volatile NioGroup nioGroup; - private volatile TcpChannelFactory clientChannelFactory; - - public NioTransport(Settings settings, ThreadPool threadPool, NetworkService networkService, BigArrays bigArrays, - PageCacheRecycler pageCacheRecycler, NamedWriteableRegistry namedWriteableRegistry, - CircuitBreakerService circuitBreakerService) { - super("nio", settings, threadPool, bigArrays, circuitBreakerService, namedWriteableRegistry, networkService); - this.pageCacheRecycler = pageCacheRecycler; - } - - @Override - protected TcpNioServerSocketChannel bind(String name, InetSocketAddress address) throws IOException { - TcpChannelFactory channelFactory = this.profileToChannelFactory.get(name); - return nioGroup.bindServerChannel(address, channelFactory); - } - - @Override - protected TcpNioSocketChannel initiateChannel(DiscoveryNode node, TimeValue connectTimeout, ActionListener connectListener) - throws IOException { - TcpNioSocketChannel channel = nioGroup.openChannel(node.getAddress().address(), clientChannelFactory); - channel.addConnectListener(connectListener); - return channel; - } - - @Override - protected void doStart() { - boolean success = false; - try { - int acceptorCount = 0; - boolean useNetworkServer = NetworkService.NETWORK_SERVER.get(settings); - if (useNetworkServer) { - acceptorCount = NioTransport.NIO_ACCEPTOR_COUNT.get(settings); - } - nioGroup = new NioGroup(logger, daemonThreadFactory(this.settings, TRANSPORT_ACCEPTOR_THREAD_NAME_PREFIX), acceptorCount, - AcceptorEventHandler::new, daemonThreadFactory(this.settings, TRANSPORT_WORKER_THREAD_NAME_PREFIX), - NioTransport.NIO_WORKER_COUNT.get(settings), this::getSocketEventHandler); - - ProfileSettings clientProfileSettings = new ProfileSettings(settings, "default"); - clientChannelFactory = new TcpChannelFactory(clientProfileSettings, getContextSetter("client"), getServerContextSetter()); - - if (useNetworkServer) { - // loop through all profiles and start them up, special handling for default one - for (ProfileSettings profileSettings : profileSettings) { - String profileName = profileSettings.profileName; - Consumer contextSetter = getContextSetter(profileName); - TcpChannelFactory factory = new TcpChannelFactory(profileSettings, contextSetter, getServerContextSetter()); - profileToChannelFactory.putIfAbsent(profileName, factory); - bindServer(profileSettings); - } - } - - super.doStart(); - success = true; - } catch (IOException e) { - throw new ElasticsearchException(e); - } finally { - if (success == false) { - doStop(); - } - } - } - - @Override - protected void stopInternal() { - try { - nioGroup.close(); - } catch (Exception e) { - logger.warn("unexpected exception while stopping nio group", e); - } - profileToChannelFactory.clear(); - } - - protected SocketEventHandler getSocketEventHandler(Logger logger) { - return new SocketEventHandler(logger); - } - - final void exceptionCaught(NioSocketChannel channel, Exception exception) { - onException((TcpNioSocketChannel) channel, exception); - } - - private Consumer getContextSetter(String profileName) { - return (c) -> { - Supplier pageSupplier = () -> { - Recycler.V bytes = pageCacheRecycler.bytePage(false); - return new InboundChannelBuffer.Page(ByteBuffer.wrap(bytes.v()), bytes); - }; - c.setContexts(new TcpReadContext(c, new TcpReadHandler(profileName, this), new InboundChannelBuffer(pageSupplier)), - new TcpWriteContext(c), this::exceptionCaught); - }; - } - - private void acceptChannel(NioSocketChannel channel) { - serverAcceptedChannel((TcpNioSocketChannel) channel); - - } - - private Consumer getServerContextSetter() { - return (c) -> c.setAcceptContext(this::acceptChannel); - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/NioTransportPlugin.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/NioTransportPlugin.java deleted file mode 100644 index e158fe6fe97c3..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/NioTransportPlugin.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.elasticsearch.common.io.stream.NamedWriteableRegistry; -import org.elasticsearch.common.network.NetworkService; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.util.BigArrays; -import org.elasticsearch.common.util.PageCacheRecycler; -import org.elasticsearch.indices.breaker.CircuitBreakerService; -import org.elasticsearch.plugins.NetworkPlugin; -import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.threadpool.ThreadPool; -import org.elasticsearch.transport.Transport; - -import java.util.Collections; -import java.util.Map; -import java.util.function.Supplier; - -public class NioTransportPlugin extends Plugin implements NetworkPlugin { - - public static final String NIO_TRANSPORT_NAME = "nio-transport"; - - @Override - public Map> getTransports(Settings settings, ThreadPool threadPool, BigArrays bigArrays, - PageCacheRecycler pageCacheRecycler, - CircuitBreakerService circuitBreakerService, - NamedWriteableRegistry namedWriteableRegistry, - NetworkService networkService) { - Settings settings1; - if (NioTransport.NIO_WORKER_COUNT.exists(settings) == false) { - // As this is only used for tests right now, limit the number of worker threads. - settings1 = Settings.builder().put(settings).put(NioTransport.NIO_WORKER_COUNT.getKey(), 2).build(); - } else { - settings1 = settings; - } - return Collections.singletonMap(NIO_TRANSPORT_NAME, - () -> new NioTransport(settings1, threadPool, networkService, bigArrays, pageCacheRecycler, namedWriteableRegistry, - circuitBreakerService)); - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/RoundRobinSupplier.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/RoundRobinSupplier.java deleted file mode 100644 index 395b955f7ab36..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/RoundRobinSupplier.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Supplier; - -public class RoundRobinSupplier implements Supplier { - - private final S[] selectors; - private final int count; - private AtomicInteger counter = new AtomicInteger(0); - - public RoundRobinSupplier(S[] selectors) { - this.count = selectors.length; - this.selectors = selectors; - } - - public S get() { - return selectors[counter.getAndIncrement() % count]; - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/SocketEventHandler.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/SocketEventHandler.java deleted file mode 100644 index 799e81dd4a413..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/SocketEventHandler.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.message.ParameterizedMessage; -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.transport.nio.channel.NioChannel; -import org.elasticsearch.transport.nio.channel.NioSocketChannel; -import org.elasticsearch.transport.nio.channel.SelectionKeyUtils; -import org.elasticsearch.transport.nio.channel.WriteContext; - -import java.io.IOException; - -/** - * Event handler designed to handle events from non-server sockets - */ -public class SocketEventHandler extends EventHandler { - - private final Logger logger; - - public SocketEventHandler(Logger logger) { - super(logger); - this.logger = logger; - } - - /** - * This method is called when a NioSocketChannel is successfully registered. It should only be called - * once per channel. - * - * @param channel that was registered - */ - void handleRegistration(NioSocketChannel channel) { - SelectionKeyUtils.setConnectAndReadInterested(channel); - } - - /** - * This method is called when an attempt to register a channel throws an exception. - * - * @param channel that was registered - * @param exception that occurred - */ - void registrationException(NioSocketChannel channel, Exception exception) { - logger.debug(() -> new ParameterizedMessage("failed to register socket channel: {}", channel), exception); - exceptionCaught(channel, exception); - } - - /** - * This method is called when a NioSocketChannel is successfully connected. It should only be called - * once per channel. - * - * @param channel that was registered - */ - void handleConnect(NioSocketChannel channel) { - SelectionKeyUtils.removeConnectInterested(channel); - } - - /** - * This method is called when an attempt to connect a channel throws an exception. - * - * @param channel that was connecting - * @param exception that occurred - */ - void connectException(NioSocketChannel channel, Exception exception) { - logger.debug(() -> new ParameterizedMessage("failed to connect to socket channel: {}", channel), exception); - exceptionCaught(channel, exception); - } - - /** - * This method is called when a channel signals it is ready for be read. All of the read logic should - * occur in this call. - * - * @param channel that can be read - */ - void handleRead(NioSocketChannel channel) throws IOException { - int bytesRead = channel.getReadContext().read(); - if (bytesRead == -1) { - handleClose(channel); - } - } - - /** - * This method is called when an attempt to read from a channel throws an exception. - * - * @param channel that was being read - * @param exception that occurred - */ - void readException(NioSocketChannel channel, Exception exception) { - logger.debug(() -> new ParameterizedMessage("exception while reading from socket channel: {}", channel), exception); - exceptionCaught(channel, exception); - } - - /** - * This method is called when a channel signals it is ready to receive writes. All of the write logic - * should occur in this call. - * - * @param channel that can be read - */ - void handleWrite(NioSocketChannel channel) throws IOException { - WriteContext channelContext = channel.getWriteContext(); - channelContext.flushChannel(); - if (channelContext.hasQueuedWriteOps()) { - SelectionKeyUtils.setWriteInterested(channel); - } else { - SelectionKeyUtils.removeWriteInterested(channel); - } - } - - /** - * This method is called when an attempt to write to a channel throws an exception. - * - * @param channel that was being written to - * @param exception that occurred - */ - void writeException(NioSocketChannel channel, Exception exception) { - logger.debug(() -> new ParameterizedMessage("exception while writing to socket channel: {}", channel), exception); - exceptionCaught(channel, exception); - } - - /** - * This method is called when handling an event from a channel fails due to an unexpected exception. - * An example would be if checking ready ops on a {@link java.nio.channels.SelectionKey} threw - * {@link java.nio.channels.CancelledKeyException}. - * - * @param channel that caused the exception - * @param exception that was thrown - */ - void genericChannelException(NioChannel channel, Exception exception) { - super.genericChannelException(channel, exception); - exceptionCaught((NioSocketChannel) channel, exception); - } - - /** - * This method is called when a listener attached to a channel operation throws an exception. - * - * @param listener that was called - * @param exception that occurred - */ - void listenerException(ActionListener listener, Exception exception) { - logger.warn(new ParameterizedMessage("exception while executing listener: {}", listener), exception); - } - - private void exceptionCaught(NioSocketChannel channel, Exception e) { - channel.getExceptionContext().accept(channel, e); - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/SocketSelector.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/SocketSelector.java deleted file mode 100644 index ee4252e40a80a..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/SocketSelector.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.transport.nio.channel.NioSocketChannel; -import org.elasticsearch.transport.nio.channel.SelectionKeyUtils; -import org.elasticsearch.transport.nio.channel.WriteContext; - -import java.io.IOException; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.ClosedSelectorException; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.util.concurrent.ConcurrentLinkedQueue; - -/** - * Selector implementation that handles {@link NioSocketChannel}. It's main piece of functionality is - * handling connect, read, and write events. - */ -public class SocketSelector extends ESSelector { - - private final ConcurrentLinkedQueue newChannels = new ConcurrentLinkedQueue<>(); - private final ConcurrentLinkedQueue queuedWrites = new ConcurrentLinkedQueue<>(); - private final SocketEventHandler eventHandler; - - public SocketSelector(SocketEventHandler eventHandler) throws IOException { - super(eventHandler); - this.eventHandler = eventHandler; - } - - public SocketSelector(SocketEventHandler eventHandler, Selector selector) throws IOException { - super(eventHandler, selector); - this.eventHandler = eventHandler; - } - - @Override - void processKey(SelectionKey selectionKey) { - NioSocketChannel nioSocketChannel = (NioSocketChannel) selectionKey.attachment(); - int ops = selectionKey.readyOps(); - if ((ops & SelectionKey.OP_CONNECT) != 0) { - attemptConnect(nioSocketChannel, true); - } - - if (nioSocketChannel.isConnectComplete()) { - if ((ops & SelectionKey.OP_WRITE) != 0) { - handleWrite(nioSocketChannel); - } - - if ((ops & SelectionKey.OP_READ) != 0) { - handleRead(nioSocketChannel); - } - } - } - - @Override - void preSelect() { - setUpNewChannels(); - handleQueuedWrites(); - } - - @Override - void cleanup() { - WriteOperation op; - while ((op = queuedWrites.poll()) != null) { - executeFailedListener(op.getListener(), new ClosedSelectorException()); - } - channelsToClose.addAll(newChannels); - } - - /** - * Schedules a NioSocketChannel to be registered by this selector. The channel will by queued and eventually - * registered next time through the event loop. - * @param nioSocketChannel the channel to register - */ - public void scheduleForRegistration(NioSocketChannel nioSocketChannel) { - newChannels.offer(nioSocketChannel); - ensureSelectorOpenForEnqueuing(newChannels, nioSocketChannel); - wakeup(); - } - - - /** - * Queues a write operation to be handled by the event loop. This can be called by any thread and is the - * api available for non-selector threads to schedule writes. - * - * @param writeOperation to be queued - */ - public void queueWrite(WriteOperation writeOperation) { - queuedWrites.offer(writeOperation); - if (isOpen() == false) { - boolean wasRemoved = queuedWrites.remove(writeOperation); - if (wasRemoved) { - writeOperation.getListener().onFailure(new ClosedSelectorException()); - } - } else { - wakeup(); - } - } - - /** - * Queues a write operation directly in a channel's buffer. Channel buffers are only safe to be accessed - * by the selector thread. As a result, this method should only be called by the selector thread. - * - * @param writeOperation to be queued in a channel's buffer - */ - public void queueWriteInChannelBuffer(WriteOperation writeOperation) { - assert isOnCurrentThread() : "Must be on selector thread"; - NioSocketChannel channel = writeOperation.getChannel(); - WriteContext context = channel.getWriteContext(); - try { - SelectionKeyUtils.setWriteInterested(channel); - context.queueWriteOperations(writeOperation); - } catch (Exception e) { - executeFailedListener(writeOperation.getListener(), e); - } - } - - /** - * Executes a success listener with consistent exception handling. This can only be called from current - * selector thread. - * - * @param listener to be executed - * @param value to provide to listener - */ - public void executeListener(ActionListener listener, V value) { - assert isOnCurrentThread() : "Must be on selector thread"; - try { - listener.onResponse(value); - } catch (Exception e) { - eventHandler.listenerException(listener, e); - } - } - - /** - * Executes a failed listener with consistent exception handling. This can only be called from current - * selector thread. - * - * @param listener to be executed - * @param exception to provide to listener - */ - public void executeFailedListener(ActionListener listener, Exception exception) { - assert isOnCurrentThread() : "Must be on selector thread"; - try { - listener.onFailure(exception); - } catch (Exception e) { - eventHandler.listenerException(listener, e); - } - } - - private void handleWrite(NioSocketChannel nioSocketChannel) { - try { - eventHandler.handleWrite(nioSocketChannel); - } catch (Exception e) { - eventHandler.writeException(nioSocketChannel, e); - } - } - - private void handleRead(NioSocketChannel nioSocketChannel) { - try { - eventHandler.handleRead(nioSocketChannel); - } catch (Exception e) { - eventHandler.readException(nioSocketChannel, e); - } - } - - private void handleQueuedWrites() { - WriteOperation writeOperation; - while ((writeOperation = queuedWrites.poll()) != null) { - if (writeOperation.getChannel().isWritable()) { - queueWriteInChannelBuffer(writeOperation); - } else { - executeFailedListener(writeOperation.getListener(), new ClosedChannelException()); - } - } - } - - private void setUpNewChannels() { - NioSocketChannel newChannel; - while ((newChannel = this.newChannels.poll()) != null) { - setupChannel(newChannel); - } - } - - private void setupChannel(NioSocketChannel newChannel) { - assert newChannel.getSelector() == this : "The channel must be registered with the selector with which it was created"; - try { - if (newChannel.isOpen()) { - newChannel.register(); - SelectionKey key = newChannel.getSelectionKey(); - key.attach(newChannel); - eventHandler.handleRegistration(newChannel); - attemptConnect(newChannel, false); - } else { - eventHandler.registrationException(newChannel, new ClosedChannelException()); - } - } catch (Exception e) { - eventHandler.registrationException(newChannel, e); - } - } - - private void attemptConnect(NioSocketChannel newChannel, boolean connectEvent) { - try { - if (newChannel.finishConnect()) { - eventHandler.handleConnect(newChannel); - } else if (connectEvent) { - eventHandler.connectException(newChannel, new IOException("Received OP_CONNECT but connect failed")); - } - } catch (Exception e) { - eventHandler.connectException(newChannel, e); - } - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/TcpReadHandler.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/TcpReadHandler.java deleted file mode 100644 index 5c2ecea54c3f0..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/TcpReadHandler.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.transport.nio.channel.NioSocketChannel; -import org.elasticsearch.transport.nio.channel.TcpNioSocketChannel; - -import java.io.IOException; - -public class TcpReadHandler { - - private final String profile; - private final NioTransport transport; - - public TcpReadHandler(String profile, NioTransport transport) { - this.profile = profile; - this.transport = transport; - } - - public void handleMessage(BytesReference reference, TcpNioSocketChannel channel, int messageBytesLength) { - try { - transport.messageReceived(reference, channel, profile, channel.getRemoteAddress(), messageBytesLength); - } catch (IOException e) { - handleException(channel, e); - } - } - - public void handleException(NioSocketChannel channel, Exception e) { - transport.exceptionCaught(channel, e); - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/WriteOperation.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/WriteOperation.java deleted file mode 100644 index 0a2ef15b0815a..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/WriteOperation.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.BytesRefIterator; -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.transport.nio.channel.NioSocketChannel; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; - -public class WriteOperation { - - private final NioSocketChannel channel; - private final ActionListener listener; - private final ByteBuffer[] buffers; - private final int[] offsets; - private final int length; - private int internalIndex; - - public WriteOperation(NioSocketChannel channel, BytesReference bytesReference, ActionListener listener) { - this.channel = channel; - this.listener = listener; - this.buffers = toByteBuffers(bytesReference); - this.offsets = new int[buffers.length]; - int offset = 0; - for (int i = 0; i < buffers.length; i++) { - ByteBuffer buffer = buffers[i]; - offsets[i] = offset; - offset += buffer.remaining(); - } - length = offset; - } - - public ByteBuffer[] getByteBuffers() { - return buffers; - } - - public ActionListener getListener() { - return listener; - } - - public NioSocketChannel getChannel() { - return channel; - } - - public boolean isFullyFlushed() { - return internalIndex == length; - } - - public int flush() throws IOException { - int written = channel.write(getBuffersToWrite()); - internalIndex += written; - return written; - } - - private ByteBuffer[] getBuffersToWrite() { - int offsetIndex = getOffsetIndex(internalIndex); - - ByteBuffer[] postIndexBuffers = new ByteBuffer[buffers.length - offsetIndex]; - - ByteBuffer firstBuffer = buffers[offsetIndex].duplicate(); - firstBuffer.position(internalIndex - offsets[offsetIndex]); - postIndexBuffers[0] = firstBuffer; - int j = 1; - for (int i = (offsetIndex + 1); i < buffers.length; ++i) { - postIndexBuffers[j++] = buffers[i].duplicate(); - } - - return postIndexBuffers; - } - - private int getOffsetIndex(int offset) { - final int i = Arrays.binarySearch(offsets, offset); - return i < 0 ? (-(i + 1)) - 1 : i; - } - - private static ByteBuffer[] toByteBuffers(BytesReference bytesReference) { - BytesRefIterator byteRefIterator = bytesReference.iterator(); - BytesRef r; - try { - // Most network messages are composed of three buffers. - ArrayList buffers = new ArrayList<>(3); - while ((r = byteRefIterator.next()) != null) { - buffers.add(ByteBuffer.wrap(r.bytes, r.offset, r.length)); - } - return buffers.toArray(new ByteBuffer[buffers.size()]); - - } catch (IOException e) { - // this is really an error since we don't do IO in our bytesreferences - throw new AssertionError("won't happen", e); - } - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/AbstractNioChannel.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/AbstractNioChannel.java deleted file mode 100644 index 046b4d4c53671..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/AbstractNioChannel.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.transport.nio.ESSelector; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.NetworkChannel; -import java.nio.channels.SelectableChannel; -import java.nio.channels.SelectionKey; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * This is a basic channel abstraction used by the {@link org.elasticsearch.transport.nio.NioTransport}. - *

- * A channel is open once it is constructed. The channel remains open and {@link #isOpen()} will return - * true until the channel is explicitly closed. - *

- * A channel lifecycle has two stages: - *

    - *
  1. OPEN - When a channel has been created. This is the state of a channel that can perform normal operations. - *
  2. CLOSED - The channel has been set to closed. All this means is that the channel has been scheduled to be - * closed. The underlying raw channel may not yet be closed. The underlying channel has been closed if the close - * future has been completed. - *
- * - * @param the type of raw channel this AbstractNioChannel uses - */ -public abstract class AbstractNioChannel implements NioChannel { - - final S socketChannel; - // This indicates if the channel has been scheduled to be closed. Read the closeFuture to determine if - // the channel close process has completed. - final AtomicBoolean isClosing = new AtomicBoolean(false); - - private final InetSocketAddress localAddress; - private final CompletableFuture closeContext = new CompletableFuture<>(); - private final ESSelector selector; - private SelectionKey selectionKey; - - AbstractNioChannel(S socketChannel, ESSelector selector) throws IOException { - this.socketChannel = socketChannel; - this.localAddress = (InetSocketAddress) socketChannel.getLocalAddress(); - this.selector = selector; - } - - @Override - public boolean isOpen() { - return closeContext.isDone() == false; - } - - @Override - public InetSocketAddress getLocalAddress() { - return localAddress; - } - - /** - * Schedules a channel to be closed by the selector event loop with which it is registered. - *

- * If the channel is open and the state can be transitioned to closed, the close operation will - * be scheduled with the event loop. - *

- * If the channel is already set to closed, it is assumed that it is already scheduled to be closed. - */ - @Override - public void close() { - if (isClosing.compareAndSet(false, true)) { - selector.queueChannelClose(this); - } - } - - /** - * Closes the channel synchronously. This method should only be called from the selector thread. - *

- * Once this method returns, the channel will be closed. - */ - @Override - public void closeFromSelector() throws IOException { - assert selector.isOnCurrentThread() : "Should only call from selector thread"; - isClosing.set(true); - if (closeContext.isDone() == false) { - try { - closeRawChannel(); - closeContext.complete(null); - } catch (IOException e) { - closeContext.completeExceptionally(e); - throw e; - } - } - } - - /** - * This method attempts to registered a channel with the raw nio selector. It also sets the selection - * key. - * - * @throws ClosedChannelException if the raw channel was closed - */ - @Override - public void register() throws ClosedChannelException { - setSelectionKey(socketChannel.register(selector.rawSelector(), 0)); - } - - @Override - public ESSelector getSelector() { - return selector; - } - - @Override - public SelectionKey getSelectionKey() { - return selectionKey; - } - - @Override - public S getRawChannel() { - return socketChannel; - } - - @Override - public void addCloseListener(ActionListener listener) { - closeContext.whenComplete(ActionListener.toBiConsumer(listener)); - } - - // Package visibility for testing - void setSelectionKey(SelectionKey selectionKey) { - this.selectionKey = selectionKey; - } - // Package visibility for testing - - void closeRawChannel() throws IOException { - socketChannel.close(); - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/ChannelFactory.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/ChannelFactory.java deleted file mode 100644 index 97433cf4d0aad..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/ChannelFactory.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import org.elasticsearch.mocksocket.PrivilegedSocketAccess; -import org.elasticsearch.transport.nio.AcceptingSelector; -import org.elasticsearch.transport.nio.SocketSelector; - -import java.io.Closeable; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.nio.channels.ServerSocketChannel; -import java.nio.channels.SocketChannel; - -public abstract class ChannelFactory { - - private final ChannelFactory.RawChannelFactory rawChannelFactory; - - /** - * This will create a {@link ChannelFactory} using the raw channel factory passed to the constructor. - * - * @param rawChannelFactory a factory that will construct the raw socket channels - */ - ChannelFactory(RawChannelFactory rawChannelFactory) { - this.rawChannelFactory = rawChannelFactory; - } - - public Socket openNioChannel(InetSocketAddress remoteAddress, SocketSelector selector) throws IOException { - SocketChannel rawChannel = rawChannelFactory.openNioChannel(remoteAddress); - Socket channel = internalCreateChannel(selector, rawChannel); - scheduleChannel(channel, selector); - return channel; - } - - public Socket acceptNioChannel(NioServerSocketChannel serverChannel, SocketSelector selector) throws IOException { - SocketChannel rawChannel = rawChannelFactory.acceptNioChannel(serverChannel); - Socket channel = internalCreateChannel(selector, rawChannel); - scheduleChannel(channel, selector); - return channel; - } - - public ServerSocket openNioServerSocketChannel(InetSocketAddress address, AcceptingSelector selector) throws IOException { - ServerSocketChannel rawChannel = rawChannelFactory.openNioServerSocketChannel(address); - ServerSocket serverChannel = internalCreateServerChannel(selector, rawChannel); - scheduleServerChannel(serverChannel, selector); - return serverChannel; - } - - /** - * This method should return a new {@link NioSocketChannel} implementation. When this method has - * returned, the channel should be fully created and setup. Read and write contexts and the channel - * exception handler should have been set. - * - * @param selector the channel will be registered with - * @param channel the raw channel - * @return the channel - * @throws IOException related to the creation of the channel - */ - public abstract Socket createChannel(SocketSelector selector, SocketChannel channel) throws IOException; - - /** - * This method should return a new {@link NioServerSocketChannel} implementation. When this method has - * returned, the channel should be fully created and setup. - * - * @param selector the channel will be registered with - * @param channel the raw channel - * @return the server channel - * @throws IOException related to the creation of the channel - */ - public abstract ServerSocket createServerChannel(AcceptingSelector selector, ServerSocketChannel channel) throws IOException; - - private Socket internalCreateChannel(SocketSelector selector, SocketChannel rawChannel) throws IOException { - try { - Socket channel = createChannel(selector, rawChannel); - assert channel.getReadContext() != null : "read context should have been set on channel"; - assert channel.getWriteContext() != null : "write context should have been set on channel"; - assert channel.getExceptionContext() != null : "exception handler should have been set on channel"; - return channel; - } catch (Exception e) { - closeRawChannel(rawChannel, e); - throw e; - } - } - - private ServerSocket internalCreateServerChannel(AcceptingSelector selector, ServerSocketChannel rawChannel) throws IOException { - try { - return createServerChannel(selector, rawChannel); - } catch (Exception e) { - closeRawChannel(rawChannel, e); - throw e; - } - } - - private void scheduleChannel(Socket channel, SocketSelector selector) { - try { - selector.scheduleForRegistration(channel); - } catch (IllegalStateException e) { - closeRawChannel(channel.getRawChannel(), e); - throw e; - } - } - - private void scheduleServerChannel(ServerSocket channel, AcceptingSelector selector) { - try { - selector.scheduleForRegistration(channel); - } catch (IllegalStateException e) { - closeRawChannel(channel.getRawChannel(), e); - throw e; - } - } - - private static void closeRawChannel(Closeable c, Exception e) { - try { - c.close(); - } catch (IOException closeException) { - e.addSuppressed(closeException); - } - } - - static class RawChannelFactory { - - private final boolean tcpNoDelay; - private final boolean tcpKeepAlive; - private final boolean tcpReusedAddress; - private final int tcpSendBufferSize; - private final int tcpReceiveBufferSize; - - RawChannelFactory(boolean tcpNoDelay, boolean tcpKeepAlive, boolean tcpReusedAddress, int tcpSendBufferSize, - int tcpReceiveBufferSize) { - this.tcpNoDelay = tcpNoDelay; - this.tcpKeepAlive = tcpKeepAlive; - this.tcpReusedAddress = tcpReusedAddress; - this.tcpSendBufferSize = tcpSendBufferSize; - this.tcpReceiveBufferSize = tcpReceiveBufferSize; - } - - SocketChannel openNioChannel(InetSocketAddress remoteAddress) throws IOException { - SocketChannel socketChannel = SocketChannel.open(); - try { - configureSocketChannel(socketChannel); - PrivilegedSocketAccess.connect(socketChannel, remoteAddress); - } catch (IOException e) { - closeRawChannel(socketChannel, e); - throw e; - } - return socketChannel; - } - - SocketChannel acceptNioChannel(NioServerSocketChannel serverChannel) throws IOException { - ServerSocketChannel serverSocketChannel = serverChannel.getRawChannel(); - SocketChannel socketChannel = PrivilegedSocketAccess.accept(serverSocketChannel); - try { - configureSocketChannel(socketChannel); - } catch (IOException e) { - closeRawChannel(socketChannel, e); - throw e; - } - return socketChannel; - } - - ServerSocketChannel openNioServerSocketChannel(InetSocketAddress address) throws IOException { - ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); - serverSocketChannel.configureBlocking(false); - java.net.ServerSocket socket = serverSocketChannel.socket(); - try { - socket.setReuseAddress(tcpReusedAddress); - serverSocketChannel.bind(address); - } catch (IOException e) { - closeRawChannel(serverSocketChannel, e); - throw e; - } - return serverSocketChannel; - } - - private void configureSocketChannel(SocketChannel channel) throws IOException { - channel.configureBlocking(false); - java.net.Socket socket = channel.socket(); - socket.setTcpNoDelay(tcpNoDelay); - socket.setKeepAlive(tcpKeepAlive); - socket.setReuseAddress(tcpReusedAddress); - if (tcpSendBufferSize > 0) { - socket.setSendBufferSize(tcpSendBufferSize); - } - if (tcpReceiveBufferSize > 0) { - socket.setSendBufferSize(tcpReceiveBufferSize); - } - } - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/NioChannel.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/NioChannel.java deleted file mode 100644 index 93bc4faa4c5d5..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/NioChannel.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.transport.nio.ESSelector; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.NetworkChannel; -import java.nio.channels.SelectionKey; - -public interface NioChannel { - - boolean isOpen(); - - InetSocketAddress getLocalAddress(); - - void close(); - - void closeFromSelector() throws IOException; - - void register() throws ClosedChannelException; - - ESSelector getSelector(); - - SelectionKey getSelectionKey(); - - NetworkChannel getRawChannel(); - - /** - * Adds a close listener to the channel. Multiple close listeners can be added. There is no guarantee - * about the order in which close listeners will be executed. If the channel is already closed, the - * listener is executed immediately. - * - * @param listener to be called at close - */ - void addCloseListener(ActionListener listener); -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/NioServerSocketChannel.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/NioServerSocketChannel.java deleted file mode 100644 index ffbd8f7a9874e..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/NioServerSocketChannel.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import org.elasticsearch.transport.nio.AcceptingSelector; - -import java.io.IOException; -import java.nio.channels.ServerSocketChannel; -import java.util.function.Consumer; - -public class NioServerSocketChannel extends AbstractNioChannel { - - private final ChannelFactory channelFactory; - private Consumer acceptContext; - - public NioServerSocketChannel(ServerSocketChannel socketChannel, ChannelFactory channelFactory, AcceptingSelector selector) - throws IOException { - super(socketChannel, selector); - this.channelFactory = channelFactory; - } - - public ChannelFactory getChannelFactory() { - return channelFactory; - } - - /** - * This method sets the accept context for a server socket channel. The accept context is called when a - * new channel is accepted. The parameter passed to the context is the new channel. - * - * @param acceptContext to call - */ - public void setAcceptContext(Consumer acceptContext) { - this.acceptContext = acceptContext; - } - - public Consumer getAcceptContext() { - return acceptContext; - } - - @Override - public String toString() { - return "NioServerSocketChannel{" + - "localAddress=" + getLocalAddress() + - '}'; - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/NioSocketChannel.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/NioSocketChannel.java deleted file mode 100644 index 06f8aec627936..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/NioSocketChannel.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.transport.nio.InboundChannelBuffer; -import org.elasticsearch.transport.nio.SocketSelector; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.nio.ByteBuffer; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.SocketChannel; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.BiConsumer; - -public class NioSocketChannel extends AbstractNioChannel { - - private final InetSocketAddress remoteAddress; - private final CompletableFuture connectContext = new CompletableFuture<>(); - private final SocketSelector socketSelector; - private final AtomicBoolean contextsSet = new AtomicBoolean(false); - private WriteContext writeContext; - private ReadContext readContext; - private BiConsumer exceptionContext; - private Exception connectException; - - public NioSocketChannel(SocketChannel socketChannel, SocketSelector selector) throws IOException { - super(socketChannel, selector); - this.remoteAddress = (InetSocketAddress) socketChannel.getRemoteAddress(); - this.socketSelector = selector; - } - - @Override - public void closeFromSelector() throws IOException { - assert socketSelector.isOnCurrentThread() : "Should only call from selector thread"; - // Even if the channel has already been closed we will clear any pending write operations just in case - if (writeContext.hasQueuedWriteOps()) { - writeContext.clearQueuedWriteOps(new ClosedChannelException()); - } - readContext.close(); - - super.closeFromSelector(); - } - - @Override - public SocketSelector getSelector() { - return socketSelector; - } - - public int write(ByteBuffer[] buffers) throws IOException { - if (buffers.length == 1) { - return socketChannel.write(buffers[0]); - } else { - return (int) socketChannel.write(buffers); - } - } - - public int read(InboundChannelBuffer buffer) throws IOException { - int bytesRead = (int) socketChannel.read(buffer.sliceBuffersFrom(buffer.getIndex())); - - if (bytesRead == -1) { - return bytesRead; - } - - buffer.incrementIndex(bytesRead); - return bytesRead; - } - - public void setContexts(ReadContext readContext, WriteContext writeContext, BiConsumer exceptionContext) { - if (contextsSet.compareAndSet(false, true)) { - this.readContext = readContext; - this.writeContext = writeContext; - this.exceptionContext = exceptionContext; - } else { - throw new IllegalStateException("Contexts on this channel were already set. They should only be once."); - } - } - - public WriteContext getWriteContext() { - return writeContext; - } - - public ReadContext getReadContext() { - return readContext; - } - - public BiConsumer getExceptionContext() { - return exceptionContext; - } - - public InetSocketAddress getRemoteAddress() { - return remoteAddress; - } - - public boolean isConnectComplete() { - return isConnectComplete0(); - } - - public boolean isWritable() { - return isClosing.get() == false; - } - - public boolean isReadable() { - return isClosing.get() == false; - } - - /** - * This method will attempt to complete the connection process for this channel. It should be called for - * new channels or for a channel that has produced a OP_CONNECT event. If this method returns true then - * the connection is complete and the channel is ready for reads and writes. If it returns false, the - * channel is not yet connected and this method should be called again when a OP_CONNECT event is - * received. - * - * @return true if the connection process is complete - * @throws IOException if an I/O error occurs - */ - public boolean finishConnect() throws IOException { - if (isConnectComplete0()) { - return true; - } else if (connectContext.isCompletedExceptionally()) { - Exception exception = connectException; - if (exception == null) { - throw new AssertionError("Should have received connection exception"); - } else if (exception instanceof IOException) { - throw (IOException) exception; - } else { - throw (RuntimeException) exception; - } - } - - boolean isConnected = socketChannel.isConnected(); - if (isConnected == false) { - isConnected = internalFinish(); - } - if (isConnected) { - connectContext.complete(null); - } - return isConnected; - } - - public void addConnectListener(ActionListener listener) { - connectContext.whenComplete(ActionListener.toBiConsumer(listener)); - } - - @Override - public String toString() { - return "NioSocketChannel{" + - "localAddress=" + getLocalAddress() + - ", remoteAddress=" + remoteAddress + - '}'; - } - - private boolean internalFinish() throws IOException { - try { - return socketChannel.finishConnect(); - } catch (IOException | RuntimeException e) { - connectException = e; - connectContext.completeExceptionally(e); - throw e; - } - } - - private boolean isConnectComplete0() { - return connectContext.isDone() && connectContext.isCompletedExceptionally() == false; - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/ReadContext.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/ReadContext.java deleted file mode 100644 index 243a6d8b239c2..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/ReadContext.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import java.io.IOException; - -public interface ReadContext extends AutoCloseable { - - int read() throws IOException; - - @Override - void close(); - -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/SelectionKeyUtils.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/SelectionKeyUtils.java deleted file mode 100644 index b0cf5552064fd..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/SelectionKeyUtils.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import java.nio.channels.CancelledKeyException; -import java.nio.channels.SelectionKey; - -public final class SelectionKeyUtils { - - private SelectionKeyUtils() {} - - public static void setWriteInterested(NioChannel channel) throws CancelledKeyException { - SelectionKey selectionKey = channel.getSelectionKey(); - selectionKey.interestOps(selectionKey.interestOps() | SelectionKey.OP_WRITE); - } - - public static void removeWriteInterested(NioChannel channel) throws CancelledKeyException { - SelectionKey selectionKey = channel.getSelectionKey(); - selectionKey.interestOps(selectionKey.interestOps() & ~SelectionKey.OP_WRITE); - } - - public static void setConnectAndReadInterested(NioChannel channel) throws CancelledKeyException { - SelectionKey selectionKey = channel.getSelectionKey(); - selectionKey.interestOps(selectionKey.interestOps() | SelectionKey.OP_CONNECT | SelectionKey.OP_READ); - } - - public static void removeConnectInterested(NioChannel channel) throws CancelledKeyException { - SelectionKey selectionKey = channel.getSelectionKey(); - selectionKey.interestOps(selectionKey.interestOps() & ~SelectionKey.OP_CONNECT); - } - - public static void setAcceptInterested(NioServerSocketChannel channel) { - SelectionKey selectionKey = channel.getSelectionKey(); - selectionKey.interestOps(selectionKey.interestOps() | SelectionKey.OP_ACCEPT); - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpChannelFactory.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpChannelFactory.java deleted file mode 100644 index 03d6db18e5a41..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpChannelFactory.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import org.elasticsearch.transport.TcpTransport; -import org.elasticsearch.transport.nio.AcceptingSelector; -import org.elasticsearch.transport.nio.SocketSelector; - -import java.io.IOException; -import java.nio.channels.ServerSocketChannel; -import java.nio.channels.SocketChannel; -import java.util.function.Consumer; - -/** - * This is an implementation of {@link ChannelFactory} which returns channels that adhere to the - * {@link org.elasticsearch.transport.TcpChannel} interface. The channels will use the provided - * {@link TcpTransport.ProfileSettings}. The provided context setters will be called with the channel after - * construction. - */ -public class TcpChannelFactory extends ChannelFactory { - - private final Consumer contextSetter; - private final Consumer serverContextSetter; - - public TcpChannelFactory(TcpTransport.ProfileSettings profileSettings, Consumer contextSetter, - Consumer serverContextSetter) { - super(new RawChannelFactory(profileSettings.tcpNoDelay, - profileSettings.tcpKeepAlive, - profileSettings.reuseAddress, - Math.toIntExact(profileSettings.sendBufferSize.getBytes()), - Math.toIntExact(profileSettings.receiveBufferSize.getBytes()))); - this.contextSetter = contextSetter; - this.serverContextSetter = serverContextSetter; - } - - @Override - public TcpNioSocketChannel createChannel(SocketSelector selector, SocketChannel channel) throws IOException { - TcpNioSocketChannel nioChannel = new TcpNioSocketChannel(channel, selector); - contextSetter.accept(nioChannel); - return nioChannel; - } - - @Override - public TcpNioServerSocketChannel createServerChannel(AcceptingSelector selector, ServerSocketChannel channel) throws IOException { - TcpNioServerSocketChannel nioServerChannel = new TcpNioServerSocketChannel(channel, this, selector); - serverContextSetter.accept(nioServerChannel); - return nioServerChannel; - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpFrameDecoder.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpFrameDecoder.java deleted file mode 100644 index b2ba70fb2365d..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpFrameDecoder.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.unit.ByteSizeValue; -import org.elasticsearch.monitor.jvm.JvmInfo; -import org.elasticsearch.transport.TcpHeader; -import org.elasticsearch.transport.TcpTransport; - -import java.io.IOException; -import java.io.StreamCorruptedException; - -public class TcpFrameDecoder { - - private static final long NINETY_PER_HEAP_SIZE = (long) (JvmInfo.jvmInfo().getMem().getHeapMax().getBytes() * 0.9); - private static final int HEADER_SIZE = TcpHeader.MARKER_BYTES_SIZE + TcpHeader.MESSAGE_LENGTH_SIZE; - - private int expectedMessageLength = -1; - - public BytesReference decode(BytesReference bytesReference) throws IOException { - if (bytesReference.length() >= 6) { - int messageLength = readHeaderBuffer(bytesReference); - int totalLength = messageLength + HEADER_SIZE; - if (totalLength > bytesReference.length()) { - expectedMessageLength = totalLength; - return null; - } else if (totalLength == bytesReference.length()) { - expectedMessageLength = -1; - return bytesReference; - } else { - expectedMessageLength = -1; - return bytesReference.slice(0, totalLength); - } - } else { - return null; - } - } - - public int expectedMessageLength() { - return expectedMessageLength; - } - - private int readHeaderBuffer(BytesReference headerBuffer) throws IOException { - if (headerBuffer.get(0) != 'E' || headerBuffer.get(1) != 'S') { - if (appearsToBeHTTP(headerBuffer)) { - throw new TcpTransport.HttpOnTransportException("This is not a HTTP port"); - } - - throw new StreamCorruptedException("invalid internal transport message format, got (" - + Integer.toHexString(headerBuffer.get(0) & 0xFF) + "," - + Integer.toHexString(headerBuffer.get(1) & 0xFF) + "," - + Integer.toHexString(headerBuffer.get(2) & 0xFF) + "," - + Integer.toHexString(headerBuffer.get(3) & 0xFF) + ")"); - } - final int messageLength; - try (StreamInput input = headerBuffer.streamInput()) { - input.skip(TcpHeader.MARKER_BYTES_SIZE); - messageLength = input.readInt(); - } - - if (messageLength == -1) { - // This is a ping - return 0; - } - - if (messageLength <= 0) { - throw new StreamCorruptedException("invalid data length: " + messageLength); - } - - if (messageLength > NINETY_PER_HEAP_SIZE) { - throw new IllegalArgumentException("transport content length received [" + new ByteSizeValue(messageLength) + "] exceeded [" - + new ByteSizeValue(NINETY_PER_HEAP_SIZE) + "]"); - } - - return messageLength; - } - - private static boolean appearsToBeHTTP(BytesReference headerBuffer) { - return bufferStartsWith(headerBuffer, "GET") || - bufferStartsWith(headerBuffer, "POST") || - bufferStartsWith(headerBuffer, "PUT") || - bufferStartsWith(headerBuffer, "HEAD") || - bufferStartsWith(headerBuffer, "DELETE") || - // TODO: Actually 'OPTIONS'. But that does not currently fit in 6 bytes - bufferStartsWith(headerBuffer, "OPTION") || - bufferStartsWith(headerBuffer, "PATCH") || - bufferStartsWith(headerBuffer, "TRACE"); - } - - private static boolean bufferStartsWith(BytesReference buffer, String method) { - char[] chars = method.toCharArray(); - for (int i = 0; i < chars.length; i++) { - if (buffer.get(i) != chars[i]) { - return false; - } - } - return true; - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpNioServerSocketChannel.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpNioServerSocketChannel.java deleted file mode 100644 index 496295bd3203b..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpNioServerSocketChannel.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.transport.TcpChannel; -import org.elasticsearch.transport.nio.AcceptingSelector; - -import java.io.IOException; -import java.nio.channels.ServerSocketChannel; - -/** - * This is an implementation of {@link NioServerSocketChannel} that adheres to the {@link TcpChannel} - * interface. As it is a server socket, setting SO_LINGER and sending messages is not supported. - */ -public class TcpNioServerSocketChannel extends NioServerSocketChannel implements TcpChannel { - - TcpNioServerSocketChannel(ServerSocketChannel socketChannel, TcpChannelFactory channelFactory, AcceptingSelector selector) - throws IOException { - super(socketChannel, channelFactory, selector); - } - - @Override - public void sendMessage(BytesReference reference, ActionListener listener) { - throw new UnsupportedOperationException("Cannot send a message to a server channel."); - } - - @Override - public void setSoLinger(int value) throws IOException { - throw new UnsupportedOperationException("Cannot set SO_LINGER on a server channel."); - } - - @Override - public String toString() { - return "TcpNioServerSocketChannel{" + - "localAddress=" + getLocalAddress() + - '}'; - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpNioSocketChannel.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpNioSocketChannel.java deleted file mode 100644 index f1ee1bd4e67ad..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpNioSocketChannel.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.transport.TcpChannel; -import org.elasticsearch.transport.nio.SocketSelector; - -import java.io.IOException; -import java.net.StandardSocketOptions; -import java.nio.channels.SocketChannel; - -public class TcpNioSocketChannel extends NioSocketChannel implements TcpChannel { - - public TcpNioSocketChannel(SocketChannel socketChannel, SocketSelector selector) throws IOException { - super(socketChannel, selector); - } - - public void sendMessage(BytesReference reference, ActionListener listener) { - getWriteContext().sendMessage(reference, listener); - } - - @Override - public void setSoLinger(int value) throws IOException { - if (isOpen()) { - getRawChannel().setOption(StandardSocketOptions.SO_LINGER, value); - } - } - - @Override - public String toString() { - return "TcpNioSocketChannel{" + - "localAddress=" + getLocalAddress() + - ", remoteAddress=" + getRemoteAddress() + - '}'; - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpReadContext.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpReadContext.java deleted file mode 100644 index 24a671412d220..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpReadContext.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import org.elasticsearch.common.bytes.ByteBufferReference; -import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.common.bytes.CompositeBytesReference; -import org.elasticsearch.transport.nio.InboundChannelBuffer; -import org.elasticsearch.transport.nio.TcpReadHandler; - -import java.io.IOException; -import java.nio.ByteBuffer; - -public class TcpReadContext implements ReadContext { - - private final TcpReadHandler handler; - private final TcpNioSocketChannel channel; - private final InboundChannelBuffer channelBuffer; - private final TcpFrameDecoder frameDecoder = new TcpFrameDecoder(); - - public TcpReadContext(NioSocketChannel channel, TcpReadHandler handler, InboundChannelBuffer channelBuffer) { - this.handler = handler; - this.channel = (TcpNioSocketChannel) channel; - this.channelBuffer = channelBuffer; - } - - @Override - public int read() throws IOException { - if (channelBuffer.getRemaining() == 0) { - // Requiring one additional byte will ensure that a new page is allocated. - channelBuffer.ensureCapacity(channelBuffer.getCapacity() + 1); - } - - int bytesRead = channel.read(channelBuffer); - - if (bytesRead == -1) { - return bytesRead; - } - - BytesReference message; - - // Frame decoder will throw an exception if the message is improperly formatted, the header is incorrect, - // or the message is corrupted - while ((message = frameDecoder.decode(toBytesReference(channelBuffer))) != null) { - int messageLengthWithHeader = message.length(); - - try { - BytesReference messageWithoutHeader = message.slice(6, message.length() - 6); - - // A message length of 6 bytes it is just a ping. Ignore for now. - if (messageLengthWithHeader != 6) { - handler.handleMessage(messageWithoutHeader, channel, messageWithoutHeader.length()); - } - } catch (Exception e) { - handler.handleException(channel, e); - } finally { - channelBuffer.release(messageLengthWithHeader); - } - } - - return bytesRead; - } - - @Override - public void close() { - channelBuffer.close(); - } - - private static BytesReference toBytesReference(InboundChannelBuffer channelBuffer) { - ByteBuffer[] writtenToBuffers = channelBuffer.sliceBuffersTo(channelBuffer.getIndex()); - ByteBufferReference[] references = new ByteBufferReference[writtenToBuffers.length]; - for (int i = 0; i < references.length; ++i) { - references[i] = new ByteBufferReference(writtenToBuffers[i]); - } - - return new CompositeBytesReference(references); - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpWriteContext.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpWriteContext.java deleted file mode 100644 index 63b876c098764..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/TcpWriteContext.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.transport.nio.SocketSelector; -import org.elasticsearch.transport.nio.WriteOperation; - -import java.io.IOException; -import java.nio.channels.ClosedChannelException; -import java.util.LinkedList; - -public class TcpWriteContext implements WriteContext { - - private final NioSocketChannel channel; - private final LinkedList queued = new LinkedList<>(); - - public TcpWriteContext(NioSocketChannel channel) { - this.channel = channel; - } - - @Override - public void sendMessage(BytesReference reference, ActionListener listener) { - if (channel.isWritable() == false) { - listener.onFailure(new ClosedChannelException()); - return; - } - - WriteOperation writeOperation = new WriteOperation(channel, reference, listener); - SocketSelector selector = channel.getSelector(); - if (selector.isOnCurrentThread() == false) { - selector.queueWrite(writeOperation); - return; - } - - // TODO: Eval if we will allow writes from sendMessage - selector.queueWriteInChannelBuffer(writeOperation); - } - - @Override - public void queueWriteOperations(WriteOperation writeOperation) { - assert channel.getSelector().isOnCurrentThread() : "Must be on selector thread to queue writes"; - queued.add(writeOperation); - } - - @Override - public void flushChannel() throws IOException { - assert channel.getSelector().isOnCurrentThread() : "Must be on selector thread to flush writes"; - int ops = queued.size(); - if (ops == 1) { - singleFlush(queued.pop()); - } else if (ops > 1) { - multiFlush(); - } - } - - @Override - public boolean hasQueuedWriteOps() { - assert channel.getSelector().isOnCurrentThread() : "Must be on selector thread to access queued writes"; - return queued.isEmpty() == false; - } - - @Override - public void clearQueuedWriteOps(Exception e) { - assert channel.getSelector().isOnCurrentThread() : "Must be on selector thread to clear queued writes"; - for (WriteOperation op : queued) { - channel.getSelector().executeFailedListener(op.getListener(), e); - } - queued.clear(); - } - - private void singleFlush(WriteOperation headOp) throws IOException { - try { - headOp.flush(); - } catch (IOException e) { - channel.getSelector().executeFailedListener(headOp.getListener(), e); - throw e; - } - - if (headOp.isFullyFlushed()) { - channel.getSelector().executeListener(headOp.getListener(), null); - } else { - queued.push(headOp); - } - } - - private void multiFlush() throws IOException { - boolean lastOpCompleted = true; - while (lastOpCompleted && queued.isEmpty() == false) { - WriteOperation op = queued.pop(); - singleFlush(op); - lastOpCompleted = op.isFullyFlushed(); - } - } -} diff --git a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/WriteContext.java b/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/WriteContext.java deleted file mode 100644 index 718b7daf8c628..0000000000000 --- a/test/framework/src/main/java/org/elasticsearch/transport/nio/channel/WriteContext.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.transport.nio.WriteOperation; - -import java.io.IOException; - -public interface WriteContext { - - void sendMessage(BytesReference reference, ActionListener listener); - - void queueWriteOperations(WriteOperation writeOperation); - - void flushChannel() throws IOException; - - boolean hasQueuedWriteOps(); - - void clearQueuedWriteOps(Exception e); - -} diff --git a/test/framework/src/test/java/org/elasticsearch/transport/nio/AcceptingSelectorTests.java b/test/framework/src/test/java/org/elasticsearch/transport/nio/AcceptingSelectorTests.java deleted file mode 100644 index 4e35f6177f5dc..0000000000000 --- a/test/framework/src/test/java/org/elasticsearch/transport/nio/AcceptingSelectorTests.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.transport.nio.channel.NioServerSocketChannel; -import org.elasticsearch.transport.nio.utils.TestSelectionKey; -import org.junit.Before; - -import java.io.IOException; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.security.PrivilegedActionException; -import java.util.Collections; -import java.util.HashSet; - -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.same; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class AcceptingSelectorTests extends ESTestCase { - - private AcceptingSelector selector; - private NioServerSocketChannel serverChannel; - private AcceptorEventHandler eventHandler; - private TestSelectionKey selectionKey; - private Selector rawSelector; - - @Before - public void setUp() throws Exception { - super.setUp(); - - eventHandler = mock(AcceptorEventHandler.class); - serverChannel = mock(NioServerSocketChannel.class); - - rawSelector = mock(Selector.class); - selector = new AcceptingSelector(eventHandler, rawSelector); - this.selector.setThread(); - - selectionKey = new TestSelectionKey(0); - selectionKey.attach(serverChannel); - when(serverChannel.getSelectionKey()).thenReturn(selectionKey); - when(serverChannel.getSelector()).thenReturn(selector); - when(serverChannel.isOpen()).thenReturn(true); - } - - public void testRegisteredChannel() throws IOException, PrivilegedActionException { - selector.scheduleForRegistration(serverChannel); - - selector.preSelect(); - - verify(eventHandler).serverChannelRegistered(serverChannel); - } - - public void testClosedChannelWillNotBeRegistered() throws Exception { - when(serverChannel.isOpen()).thenReturn(false); - selector.scheduleForRegistration(serverChannel); - - selector.preSelect(); - - verify(eventHandler).registrationException(same(serverChannel), any(ClosedChannelException.class)); - } - - public void testRegisterChannelFailsDueToException() throws Exception { - selector.scheduleForRegistration(serverChannel); - - ClosedChannelException closedChannelException = new ClosedChannelException(); - doThrow(closedChannelException).when(serverChannel).register(); - - selector.preSelect(); - - verify(eventHandler).registrationException(serverChannel, closedChannelException); - } - - public void testAcceptEvent() throws IOException { - selectionKey.setReadyOps(SelectionKey.OP_ACCEPT); - - selector.processKey(selectionKey); - - verify(eventHandler).acceptChannel(serverChannel); - } - - public void testAcceptException() throws IOException { - selectionKey.setReadyOps(SelectionKey.OP_ACCEPT); - IOException ioException = new IOException(); - - doThrow(ioException).when(eventHandler).acceptChannel(serverChannel); - - selector.processKey(selectionKey); - - verify(eventHandler).acceptException(serverChannel, ioException); - } - - public void testCleanup() throws IOException { - selector.scheduleForRegistration(serverChannel); - - selector.preSelect(); - - TestSelectionKey key = new TestSelectionKey(0); - key.attach(serverChannel); - when(rawSelector.keys()).thenReturn(new HashSet<>(Collections.singletonList(key))); - - selector.cleanupAndCloseChannels(); - - verify(eventHandler).handleClose(serverChannel); - } -} diff --git a/test/framework/src/test/java/org/elasticsearch/transport/nio/AcceptorEventHandlerTests.java b/test/framework/src/test/java/org/elasticsearch/transport/nio/AcceptorEventHandlerTests.java deleted file mode 100644 index 48a9e65f00dff..0000000000000 --- a/test/framework/src/test/java/org/elasticsearch/transport/nio/AcceptorEventHandlerTests.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.transport.nio.channel.ChannelFactory; -import org.elasticsearch.transport.nio.channel.DoNotRegisterServerChannel; -import org.elasticsearch.transport.nio.channel.NioServerSocketChannel; -import org.elasticsearch.transport.nio.channel.NioSocketChannel; -import org.elasticsearch.transport.nio.channel.ReadContext; -import org.elasticsearch.transport.nio.channel.WriteContext; -import org.junit.Before; - -import java.io.IOException; -import java.nio.channels.SelectionKey; -import java.nio.channels.ServerSocketChannel; -import java.nio.channels.SocketChannel; -import java.util.ArrayList; -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -import static org.mockito.Matchers.same; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class AcceptorEventHandlerTests extends ESTestCase { - - private AcceptorEventHandler handler; - private SocketSelector socketSelector; - private ChannelFactory channelFactory; - private NioServerSocketChannel channel; - private Consumer acceptedChannelCallback; - - @Before - @SuppressWarnings("unchecked") - public void setUpHandler() throws IOException { - channelFactory = mock(ChannelFactory.class); - socketSelector = mock(SocketSelector.class); - acceptedChannelCallback = mock(Consumer.class); - ArrayList selectors = new ArrayList<>(); - selectors.add(socketSelector); - handler = new AcceptorEventHandler(logger, new RoundRobinSupplier<>(selectors.toArray(new SocketSelector[selectors.size()]))); - - AcceptingSelector selector = mock(AcceptingSelector.class); - channel = new DoNotRegisterServerChannel(mock(ServerSocketChannel.class), channelFactory, selector); - channel.setAcceptContext(acceptedChannelCallback); - channel.register(); - } - - public void testHandleRegisterSetsOP_ACCEPTInterest() { - assertEquals(0, channel.getSelectionKey().interestOps()); - - handler.serverChannelRegistered(channel); - - assertEquals(SelectionKey.OP_ACCEPT, channel.getSelectionKey().interestOps()); - } - - public void testHandleAcceptCallsChannelFactory() throws IOException { - NioSocketChannel childChannel = new NioSocketChannel(mock(SocketChannel.class), socketSelector); - when(channelFactory.acceptNioChannel(same(channel), same(socketSelector))).thenReturn(childChannel); - - handler.acceptChannel(channel); - - verify(channelFactory).acceptNioChannel(same(channel), same(socketSelector)); - - } - - @SuppressWarnings("unchecked") - public void testHandleAcceptCallsServerAcceptCallback() throws IOException { - NioSocketChannel childChannel = new NioSocketChannel(mock(SocketChannel.class), socketSelector); - childChannel.setContexts(mock(ReadContext.class), mock(WriteContext.class), mock(BiConsumer.class)); - when(channelFactory.acceptNioChannel(same(channel), same(socketSelector))).thenReturn(childChannel); - - handler.acceptChannel(channel); - - verify(acceptedChannelCallback).accept(childChannel); - } -} diff --git a/test/framework/src/test/java/org/elasticsearch/transport/nio/ESSelectorTests.java b/test/framework/src/test/java/org/elasticsearch/transport/nio/ESSelectorTests.java deleted file mode 100644 index 6459447c1a865..0000000000000 --- a/test/framework/src/test/java/org/elasticsearch/transport/nio/ESSelectorTests.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.transport.nio.channel.NioChannel; -import org.junit.Before; - -import java.io.IOException; -import java.nio.channels.CancelledKeyException; -import java.nio.channels.ClosedSelectorException; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; - -import static org.mockito.Matchers.anyInt; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class ESSelectorTests extends ESTestCase { - - private ESSelector selector; - private EventHandler handler; - private Selector rawSelector; - - @Before - public void setUp() throws Exception { - super.setUp(); - handler = mock(EventHandler.class); - rawSelector = mock(Selector.class); - selector = new TestSelector(handler, rawSelector); - } - - public void testQueueChannelForClosed() throws IOException { - NioChannel channel = mock(NioChannel.class); - when(channel.getSelector()).thenReturn(selector); - - selector.queueChannelClose(channel); - - selector.singleLoop(); - - verify(handler).handleClose(channel); - } - - public void testSelectorClosedExceptionIsNotCaughtWhileRunning() throws IOException { - boolean closedSelectorExceptionCaught = false; - when(rawSelector.select(anyInt())).thenThrow(new ClosedSelectorException()); - try { - this.selector.singleLoop(); - } catch (ClosedSelectorException e) { - closedSelectorExceptionCaught = true; - } - - assertTrue(closedSelectorExceptionCaught); - } - - public void testIOExceptionWhileSelect() throws IOException { - IOException ioException = new IOException(); - - when(rawSelector.select(anyInt())).thenThrow(ioException); - - this.selector.singleLoop(); - - verify(handler).selectException(ioException); - } - - public void testSelectorClosedIfOpenAndEventLoopNotRunning() throws IOException { - when(rawSelector.isOpen()).thenReturn(true); - selector.close(); - verify(rawSelector).close(); - } - - private static class TestSelector extends ESSelector { - - TestSelector(EventHandler eventHandler, Selector selector) throws IOException { - super(eventHandler, selector); - } - - @Override - void processKey(SelectionKey selectionKey) throws CancelledKeyException { - - } - - @Override - void preSelect() { - - } - - @Override - void cleanup() { - - } - } - -} diff --git a/test/framework/src/test/java/org/elasticsearch/transport/nio/InboundChannelBufferTests.java b/test/framework/src/test/java/org/elasticsearch/transport/nio/InboundChannelBufferTests.java deleted file mode 100644 index 9620f4c9c7660..0000000000000 --- a/test/framework/src/test/java/org/elasticsearch/transport/nio/InboundChannelBufferTests.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.elasticsearch.common.util.BigArrays; -import org.elasticsearch.test.ESTestCase; - -import java.nio.ByteBuffer; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Supplier; - -public class InboundChannelBufferTests extends ESTestCase { - - private static final int PAGE_SIZE = BigArrays.PAGE_SIZE_IN_BYTES; - private final Supplier defaultPageSupplier = () -> - new InboundChannelBuffer.Page(ByteBuffer.allocate(BigArrays.BYTE_PAGE_SIZE), () -> {}); - - public void testNewBufferHasSinglePage() { - InboundChannelBuffer channelBuffer = new InboundChannelBuffer(defaultPageSupplier); - - assertEquals(PAGE_SIZE, channelBuffer.getCapacity()); - assertEquals(PAGE_SIZE, channelBuffer.getRemaining()); - assertEquals(0, channelBuffer.getIndex()); - } - - public void testExpandCapacity() { - InboundChannelBuffer channelBuffer = new InboundChannelBuffer(defaultPageSupplier); - - assertEquals(PAGE_SIZE, channelBuffer.getCapacity()); - assertEquals(PAGE_SIZE, channelBuffer.getRemaining()); - - channelBuffer.ensureCapacity(PAGE_SIZE + 1); - - assertEquals(PAGE_SIZE * 2, channelBuffer.getCapacity()); - assertEquals(PAGE_SIZE * 2, channelBuffer.getRemaining()); - } - - public void testExpandCapacityMultiplePages() { - InboundChannelBuffer channelBuffer = new InboundChannelBuffer(defaultPageSupplier); - - assertEquals(PAGE_SIZE, channelBuffer.getCapacity()); - - int multiple = randomInt(80); - channelBuffer.ensureCapacity(PAGE_SIZE + ((multiple * PAGE_SIZE) - randomInt(500))); - - assertEquals(PAGE_SIZE * (multiple + 1), channelBuffer.getCapacity()); - assertEquals(PAGE_SIZE * (multiple + 1), channelBuffer.getRemaining()); - } - - public void testExpandCapacityRespectsOffset() { - InboundChannelBuffer channelBuffer = new InboundChannelBuffer(defaultPageSupplier); - - assertEquals(PAGE_SIZE, channelBuffer.getCapacity()); - assertEquals(PAGE_SIZE, channelBuffer.getRemaining()); - - int offset = randomInt(300); - - channelBuffer.release(offset); - - assertEquals(PAGE_SIZE - offset, channelBuffer.getCapacity()); - assertEquals(PAGE_SIZE - offset, channelBuffer.getRemaining()); - - channelBuffer.ensureCapacity(PAGE_SIZE + 1); - - assertEquals(PAGE_SIZE * 2 - offset, channelBuffer.getCapacity()); - assertEquals(PAGE_SIZE * 2 - offset, channelBuffer.getRemaining()); - } - - public void testIncrementIndex() { - InboundChannelBuffer channelBuffer = new InboundChannelBuffer(defaultPageSupplier); - - assertEquals(0, channelBuffer.getIndex()); - assertEquals(PAGE_SIZE, channelBuffer.getRemaining()); - - channelBuffer.incrementIndex(10); - - assertEquals(10, channelBuffer.getIndex()); - assertEquals(PAGE_SIZE - 10, channelBuffer.getRemaining()); - } - - public void testIncrementIndexWithOffset() { - InboundChannelBuffer channelBuffer = new InboundChannelBuffer(defaultPageSupplier); - - assertEquals(0, channelBuffer.getIndex()); - assertEquals(PAGE_SIZE, channelBuffer.getRemaining()); - - channelBuffer.release(10); - assertEquals(PAGE_SIZE - 10, channelBuffer.getRemaining()); - - channelBuffer.incrementIndex(10); - - assertEquals(10, channelBuffer.getIndex()); - assertEquals(PAGE_SIZE - 20, channelBuffer.getRemaining()); - - channelBuffer.release(2); - assertEquals(8, channelBuffer.getIndex()); - assertEquals(PAGE_SIZE - 20, channelBuffer.getRemaining()); - } - - public void testReleaseClosesPages() { - ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue<>(); - Supplier supplier = () -> { - AtomicBoolean atomicBoolean = new AtomicBoolean(); - queue.add(atomicBoolean); - return new InboundChannelBuffer.Page(ByteBuffer.allocate(PAGE_SIZE), () -> atomicBoolean.set(true)); - }; - InboundChannelBuffer channelBuffer = new InboundChannelBuffer(supplier); - channelBuffer.ensureCapacity(PAGE_SIZE * 4); - - assertEquals(PAGE_SIZE * 4, channelBuffer.getCapacity()); - assertEquals(4, queue.size()); - - for (AtomicBoolean closedRef : queue) { - assertFalse(closedRef.get()); - } - - channelBuffer.release(2 * PAGE_SIZE); - - assertEquals(PAGE_SIZE * 2, channelBuffer.getCapacity()); - - assertTrue(queue.poll().get()); - assertTrue(queue.poll().get()); - assertFalse(queue.poll().get()); - assertFalse(queue.poll().get()); - } - - public void testClose() { - ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue<>(); - Supplier supplier = () -> { - AtomicBoolean atomicBoolean = new AtomicBoolean(); - queue.add(atomicBoolean); - return new InboundChannelBuffer.Page(ByteBuffer.allocate(PAGE_SIZE), () -> atomicBoolean.set(true)); - }; - InboundChannelBuffer channelBuffer = new InboundChannelBuffer(supplier); - channelBuffer.ensureCapacity(PAGE_SIZE * 4); - - assertEquals(4, queue.size()); - - for (AtomicBoolean closedRef : queue) { - assertFalse(closedRef.get()); - } - - channelBuffer.close(); - - for (AtomicBoolean closedRef : queue) { - assertTrue(closedRef.get()); - } - - expectThrows(IllegalStateException.class, () -> channelBuffer.ensureCapacity(1)); - } - - public void testAccessByteBuffers() { - InboundChannelBuffer channelBuffer = new InboundChannelBuffer(defaultPageSupplier); - - int pages = randomInt(50) + 5; - channelBuffer.ensureCapacity(pages * PAGE_SIZE); - - long capacity = channelBuffer.getCapacity(); - - ByteBuffer[] postIndexBuffers = channelBuffer.sliceBuffersFrom(channelBuffer.getIndex()); - int i = 0; - for (ByteBuffer buffer : postIndexBuffers) { - while (buffer.hasRemaining()) { - buffer.put((byte) (i++ % 127)); - } - } - - int indexIncremented = 0; - int bytesReleased = 0; - while (indexIncremented < capacity) { - assertEquals(indexIncremented - bytesReleased, channelBuffer.getIndex()); - - long amountToInc = Math.min(randomInt(2000), channelBuffer.getRemaining()); - ByteBuffer[] postIndexBuffers2 = channelBuffer.sliceBuffersFrom(channelBuffer.getIndex()); - assertEquals((byte) ((channelBuffer.getIndex() + bytesReleased) % 127), postIndexBuffers2[0].get()); - ByteBuffer[] preIndexBuffers = channelBuffer.sliceBuffersTo(channelBuffer.getIndex()); - if (preIndexBuffers.length > 0) { - ByteBuffer preIndexBuffer = preIndexBuffers[preIndexBuffers.length - 1]; - assertEquals((byte) ((channelBuffer.getIndex() + bytesReleased - 1) % 127), preIndexBuffer.get(preIndexBuffer.limit() - 1)); - } - if (randomBoolean()) { - long bytesToRelease = Math.min(randomInt(50), channelBuffer.getIndex()); - channelBuffer.release(bytesToRelease); - bytesReleased += bytesToRelease; - } - channelBuffer.incrementIndex(amountToInc); - indexIncremented += amountToInc; - } - - assertEquals(0, channelBuffer.sliceBuffersFrom(channelBuffer.getIndex()).length); - } -} diff --git a/test/framework/src/test/java/org/elasticsearch/transport/nio/NioGroupTests.java b/test/framework/src/test/java/org/elasticsearch/transport/nio/NioGroupTests.java deleted file mode 100644 index f9b3cbb4e5026..0000000000000 --- a/test/framework/src/test/java/org/elasticsearch/transport/nio/NioGroupTests.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.elasticsearch.common.CheckedRunnable; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.transport.nio.channel.ChannelFactory; - -import java.io.IOException; -import java.net.InetSocketAddress; - -import static org.elasticsearch.common.util.concurrent.EsExecutors.daemonThreadFactory; -import static org.mockito.Mockito.mock; - -public class NioGroupTests extends ESTestCase { - - private NioGroup nioGroup; - - @Override - public void setUp() throws Exception { - super.setUp(); - nioGroup = new NioGroup(logger, daemonThreadFactory(Settings.EMPTY, "acceptor"), 1, AcceptorEventHandler::new, - daemonThreadFactory(Settings.EMPTY, "selector"), 1, SocketEventHandler::new); - } - - @Override - public void tearDown() throws Exception { - nioGroup.close(); - super.tearDown(); - } - - public void testStartAndClose() throws IOException { - // ctor starts threads. So we are testing that close() stops the threads. Our thread linger checks - // will throw an exception is stop fails - nioGroup.close(); - } - - @SuppressWarnings("unchecked") - public void testCannotOperateAfterClose() throws IOException { - nioGroup.close(); - - IllegalStateException ise = expectThrows(IllegalStateException.class, - () -> nioGroup.bindServerChannel(mock(InetSocketAddress.class), mock(ChannelFactory.class))); - assertEquals("NioGroup is closed.", ise.getMessage()); - ise = expectThrows(IllegalStateException.class, - () -> nioGroup.openChannel(mock(InetSocketAddress.class), mock(ChannelFactory.class))); - assertEquals("NioGroup is closed.", ise.getMessage()); - } - - public void testCanCloseTwice() throws IOException { - nioGroup.close(); - nioGroup.close(); - } - - public void testExceptionAtStartIsHandled() throws IOException { - RuntimeException ex = new RuntimeException(); - CheckedRunnable ctor = () -> new NioGroup(logger, r -> {throw ex;}, 1, - AcceptorEventHandler::new, daemonThreadFactory(Settings.EMPTY, "selector"), 1, SocketEventHandler::new); - RuntimeException runtimeException = expectThrows(RuntimeException.class, ctor::run); - assertSame(ex, runtimeException); - // ctor starts threads. So we are testing that a failure to construct will stop threads. Our thread - // linger checks will throw an exception is stop fails - } -} diff --git a/test/framework/src/test/java/org/elasticsearch/transport/nio/SimpleNioTransportTests.java b/test/framework/src/test/java/org/elasticsearch/transport/nio/SimpleNioTransportTests.java deleted file mode 100644 index a4786b4f3d8e6..0000000000000 --- a/test/framework/src/test/java/org/elasticsearch/transport/nio/SimpleNioTransportTests.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.apache.logging.log4j.Logger; -import org.elasticsearch.Version; -import org.elasticsearch.cluster.node.DiscoveryNode; -import org.elasticsearch.common.io.stream.NamedWriteableRegistry; -import org.elasticsearch.common.network.NetworkService; -import org.elasticsearch.common.settings.ClusterSettings; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.transport.TransportAddress; -import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.common.util.BigArrays; -import org.elasticsearch.common.util.MockPageCacheRecycler; -import org.elasticsearch.indices.breaker.NoneCircuitBreakerService; -import org.elasticsearch.node.Node; -import org.elasticsearch.test.transport.MockTransportService; -import org.elasticsearch.threadpool.ThreadPool; -import org.elasticsearch.transport.AbstractSimpleTransportTestCase; -import org.elasticsearch.transport.BindTransportException; -import org.elasticsearch.transport.ConnectTransportException; -import org.elasticsearch.transport.TcpChannel; -import org.elasticsearch.transport.TcpTransport; -import org.elasticsearch.transport.Transport; -import org.elasticsearch.transport.TransportService; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Collections; - -import static java.util.Collections.emptyMap; -import static java.util.Collections.emptySet; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.instanceOf; - -public class SimpleNioTransportTests extends AbstractSimpleTransportTestCase { - - public static MockTransportService nioFromThreadPool(Settings settings, ThreadPool threadPool, final Version version, - ClusterSettings clusterSettings, boolean doHandshake) { - NamedWriteableRegistry namedWriteableRegistry = new NamedWriteableRegistry(Collections.emptyList()); - NetworkService networkService = new NetworkService(Collections.emptyList()); - Transport transport = new NioTransport(settings, threadPool, - networkService, BigArrays.NON_RECYCLING_INSTANCE, new MockPageCacheRecycler(settings), namedWriteableRegistry, - new NoneCircuitBreakerService()) { - - @Override - protected Version executeHandshake(DiscoveryNode node, TcpChannel channel, TimeValue timeout) throws IOException, - InterruptedException { - if (doHandshake) { - return super.executeHandshake(node, channel, timeout); - } else { - return version.minimumCompatibilityVersion(); - } - } - - @Override - protected Version getCurrentVersion() { - return version; - } - - @Override - protected SocketEventHandler getSocketEventHandler(Logger logger) { - return new TestingSocketEventHandler(logger); - } - }; - MockTransportService mockTransportService = - MockTransportService.createNewService(Settings.EMPTY, transport, version, threadPool, clusterSettings, Collections.emptySet()); - mockTransportService.start(); - return mockTransportService; - } - - @Override - protected MockTransportService build(Settings settings, Version version, ClusterSettings clusterSettings, boolean doHandshake) { - settings = Settings.builder().put(settings) - .put(TcpTransport.PORT.getKey(), "0") - .build(); - MockTransportService transportService = nioFromThreadPool(settings, threadPool, version, clusterSettings, doHandshake); - transportService.start(); - return transportService; - } - - @Override - protected void closeConnectionChannel(Transport transport, Transport.Connection connection) throws IOException { - @SuppressWarnings("unchecked") - TcpTransport.NodeChannels channels = (TcpTransport.NodeChannels) connection; - TcpChannel.closeChannels(channels.getChannels().subList(0, randomIntBetween(1, channels.getChannels().size())), true); - } - - public void testConnectException() throws UnknownHostException { - try { - serviceA.connectToNode(new DiscoveryNode("C", new TransportAddress(InetAddress.getByName("localhost"), 9876), - emptyMap(), emptySet(),Version.CURRENT)); - fail("Expected ConnectTransportException"); - } catch (ConnectTransportException e) { - assertThat(e.getMessage(), containsString("connect_exception")); - assertThat(e.getMessage(), containsString("[127.0.0.1:9876]")); - Throwable cause = e.getCause(); - assertThat(cause, instanceOf(IOException.class)); - } - } - - public void testBindUnavailableAddress() { - // this is on a lower level since it needs access to the TransportService before it's started - int port = serviceA.boundAddress().publishAddress().getPort(); - Settings settings = Settings.builder() - .put(Node.NODE_NAME_SETTING.getKey(), "foobar") - .put(TransportService.TRACE_LOG_INCLUDE_SETTING.getKey(), "") - .put(TransportService.TRACE_LOG_EXCLUDE_SETTING.getKey(), "NOTHING") - .put("transport.tcp.port", port) - .build(); - ClusterSettings clusterSettings = new ClusterSettings(settings, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS); - BindTransportException bindTransportException = expectThrows(BindTransportException.class, () -> { - MockTransportService transportService = nioFromThreadPool(settings, threadPool, Version.CURRENT, clusterSettings, true); - try { - transportService.start(); - } finally { - transportService.stop(); - transportService.close(); - } - }); - assertEquals("Failed to bind to ["+ port + "]", bindTransportException.getMessage()); - } -} diff --git a/test/framework/src/test/java/org/elasticsearch/transport/nio/SocketEventHandlerTests.java b/test/framework/src/test/java/org/elasticsearch/transport/nio/SocketEventHandlerTests.java deleted file mode 100644 index b547273d30925..0000000000000 --- a/test/framework/src/test/java/org/elasticsearch/transport/nio/SocketEventHandlerTests.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.common.bytes.BytesArray; -import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.transport.nio.channel.DoNotRegisterChannel; -import org.elasticsearch.transport.nio.channel.NioChannel; -import org.elasticsearch.transport.nio.channel.NioSocketChannel; -import org.elasticsearch.transport.nio.channel.ReadContext; -import org.elasticsearch.transport.nio.channel.SelectionKeyUtils; -import org.elasticsearch.transport.nio.channel.TcpWriteContext; -import org.junit.Before; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.CancelledKeyException; -import java.nio.channels.SelectionKey; -import java.nio.channels.SocketChannel; -import java.util.function.BiConsumer; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class SocketEventHandlerTests extends ESTestCase { - - private BiConsumer exceptionHandler; - - private SocketEventHandler handler; - private NioSocketChannel channel; - private ReadContext readContext; - private SocketChannel rawChannel; - - @Before - @SuppressWarnings("unchecked") - public void setUpHandler() throws IOException { - exceptionHandler = mock(BiConsumer.class); - SocketSelector socketSelector = mock(SocketSelector.class); - handler = new SocketEventHandler(logger); - rawChannel = mock(SocketChannel.class); - channel = new DoNotRegisterChannel(rawChannel, socketSelector); - readContext = mock(ReadContext.class); - when(rawChannel.finishConnect()).thenReturn(true); - - channel.setContexts(readContext, new TcpWriteContext(channel), exceptionHandler); - channel.register(); - channel.finishConnect(); - - when(socketSelector.isOnCurrentThread()).thenReturn(true); - } - - public void testRegisterAddsOP_CONNECTAndOP_READInterest() throws IOException { - handler.handleRegistration(channel); - assertEquals(SelectionKey.OP_READ | SelectionKey.OP_CONNECT, channel.getSelectionKey().interestOps()); - } - - public void testRegistrationExceptionCallsExceptionHandler() throws IOException { - CancelledKeyException exception = new CancelledKeyException(); - handler.registrationException(channel, exception); - verify(exceptionHandler).accept(channel, exception); - } - - public void testConnectRemovesOP_CONNECTInterest() throws IOException { - SelectionKeyUtils.setConnectAndReadInterested(channel); - handler.handleConnect(channel); - assertEquals(SelectionKey.OP_READ, channel.getSelectionKey().interestOps()); - } - - public void testConnectExceptionCallsExceptionHandler() throws IOException { - IOException exception = new IOException(); - handler.connectException(channel, exception); - verify(exceptionHandler).accept(channel, exception); - } - - public void testHandleReadDelegatesToReadContext() throws IOException { - when(readContext.read()).thenReturn(1); - - handler.handleRead(channel); - - verify(readContext).read(); - } - - public void testHandleReadMarksChannelForCloseIfPeerClosed() throws IOException { - NioSocketChannel nioSocketChannel = mock(NioSocketChannel.class); - when(nioSocketChannel.getReadContext()).thenReturn(readContext); - when(readContext.read()).thenReturn(-1); - - handler.handleRead(nioSocketChannel); - - verify(nioSocketChannel).closeFromSelector(); - } - - public void testReadExceptionCallsExceptionHandler() throws IOException { - IOException exception = new IOException(); - handler.readException(channel, exception); - verify(exceptionHandler).accept(channel, exception); - } - - @SuppressWarnings("unchecked") - public void testHandleWriteWithCompleteFlushRemovesOP_WRITEInterest() throws IOException { - SelectionKey selectionKey = channel.getSelectionKey(); - setWriteAndRead(channel); - assertEquals(SelectionKey.OP_READ | SelectionKey.OP_WRITE, selectionKey.interestOps()); - - BytesArray bytesArray = new BytesArray(new byte[1]); - channel.getWriteContext().queueWriteOperations(new WriteOperation(channel, bytesArray, mock(ActionListener.class))); - - when(rawChannel.write(ByteBuffer.wrap(bytesArray.array()))).thenReturn(1); - handler.handleWrite(channel); - - assertEquals(SelectionKey.OP_READ, selectionKey.interestOps()); - } - - @SuppressWarnings("unchecked") - public void testHandleWriteWithInCompleteFlushLeavesOP_WRITEInterest() throws IOException { - SelectionKey selectionKey = channel.getSelectionKey(); - setWriteAndRead(channel); - assertEquals(SelectionKey.OP_READ | SelectionKey.OP_WRITE, selectionKey.interestOps()); - - BytesArray bytesArray = new BytesArray(new byte[1]); - channel.getWriteContext().queueWriteOperations(new WriteOperation(channel, bytesArray, mock(ActionListener.class))); - - when(rawChannel.write(ByteBuffer.wrap(bytesArray.array()))).thenReturn(0); - handler.handleWrite(channel); - - assertEquals(SelectionKey.OP_READ | SelectionKey.OP_WRITE, selectionKey.interestOps()); - } - - public void testHandleWriteWithNoOpsRemovesOP_WRITEInterest() throws IOException { - SelectionKey selectionKey = channel.getSelectionKey(); - setWriteAndRead(channel); - assertEquals(SelectionKey.OP_READ | SelectionKey.OP_WRITE, channel.getSelectionKey().interestOps()); - - handler.handleWrite(channel); - - assertEquals(SelectionKey.OP_READ, selectionKey.interestOps()); - } - - private void setWriteAndRead(NioChannel channel) { - SelectionKeyUtils.setConnectAndReadInterested(channel); - SelectionKeyUtils.removeConnectInterested(channel); - SelectionKeyUtils.setWriteInterested(channel); - } - - public void testWriteExceptionCallsExceptionHandler() throws IOException { - IOException exception = new IOException(); - handler.writeException(channel, exception); - verify(exceptionHandler).accept(channel, exception); - } -} diff --git a/test/framework/src/test/java/org/elasticsearch/transport/nio/SocketSelectorTests.java b/test/framework/src/test/java/org/elasticsearch/transport/nio/SocketSelectorTests.java deleted file mode 100644 index 1b67d9d099b27..0000000000000 --- a/test/framework/src/test/java/org/elasticsearch/transport/nio/SocketSelectorTests.java +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.common.bytes.BytesArray; -import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.transport.nio.channel.NioSocketChannel; -import org.elasticsearch.transport.nio.channel.WriteContext; -import org.elasticsearch.transport.nio.utils.TestSelectionKey; -import org.junit.Before; - -import java.io.IOException; -import java.nio.channels.CancelledKeyException; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.ClosedSelectorException; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.util.Collections; -import java.util.HashSet; - -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.same; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class SocketSelectorTests extends ESTestCase { - - private SocketSelector socketSelector; - private SocketEventHandler eventHandler; - private NioSocketChannel channel; - private TestSelectionKey selectionKey; - private WriteContext writeContext; - private ActionListener listener; - private BytesReference bufferReference = new BytesArray(new byte[1]); - private Selector rawSelector; - - @Before - @SuppressWarnings("unchecked") - public void setUp() throws Exception { - super.setUp(); - eventHandler = mock(SocketEventHandler.class); - channel = mock(NioSocketChannel.class); - writeContext = mock(WriteContext.class); - listener = mock(ActionListener.class); - selectionKey = new TestSelectionKey(0); - selectionKey.attach(channel); - rawSelector = mock(Selector.class); - - this.socketSelector = new SocketSelector(eventHandler, rawSelector); - this.socketSelector.setThread(); - - when(channel.isOpen()).thenReturn(true); - when(channel.getSelectionKey()).thenReturn(selectionKey); - when(channel.getWriteContext()).thenReturn(writeContext); - when(channel.isConnectComplete()).thenReturn(true); - when(channel.getSelector()).thenReturn(socketSelector); - } - - public void testRegisterChannel() throws Exception { - socketSelector.scheduleForRegistration(channel); - - socketSelector.preSelect(); - - verify(eventHandler).handleRegistration(channel); - } - - public void testClosedChannelWillNotBeRegistered() throws Exception { - when(channel.isOpen()).thenReturn(false); - socketSelector.scheduleForRegistration(channel); - - socketSelector.preSelect(); - - verify(eventHandler).registrationException(same(channel), any(ClosedChannelException.class)); - verify(channel, times(0)).finishConnect(); - } - - public void testRegisterChannelFailsDueToException() throws Exception { - socketSelector.scheduleForRegistration(channel); - - ClosedChannelException closedChannelException = new ClosedChannelException(); - doThrow(closedChannelException).when(channel).register(); - - socketSelector.preSelect(); - - verify(eventHandler).registrationException(channel, closedChannelException); - verify(channel, times(0)).finishConnect(); - } - - public void testSuccessfullyRegisterChannelWillConnect() throws Exception { - socketSelector.scheduleForRegistration(channel); - - when(channel.finishConnect()).thenReturn(true); - - socketSelector.preSelect(); - - verify(eventHandler).handleConnect(channel); - } - - public void testConnectIncompleteWillNotNotify() throws Exception { - socketSelector.scheduleForRegistration(channel); - - when(channel.finishConnect()).thenReturn(false); - - socketSelector.preSelect(); - - verify(eventHandler, times(0)).handleConnect(channel); - } - - public void testQueueWriteWhenNotRunning() throws Exception { - socketSelector.close(); - - socketSelector.queueWrite(new WriteOperation(channel, bufferReference, listener)); - - verify(listener).onFailure(any(ClosedSelectorException.class)); - } - - public void testQueueWriteChannelIsNoLongerWritable() throws Exception { - WriteOperation writeOperation = new WriteOperation(channel, bufferReference, listener); - socketSelector.queueWrite(writeOperation); - - when(channel.isWritable()).thenReturn(false); - socketSelector.preSelect(); - - verify(writeContext, times(0)).queueWriteOperations(writeOperation); - verify(listener).onFailure(any(ClosedChannelException.class)); - } - - public void testQueueWriteSelectionKeyThrowsException() throws Exception { - SelectionKey selectionKey = mock(SelectionKey.class); - - WriteOperation writeOperation = new WriteOperation(channel, bufferReference, listener); - CancelledKeyException cancelledKeyException = new CancelledKeyException(); - socketSelector.queueWrite(writeOperation); - - when(channel.isWritable()).thenReturn(true); - when(channel.getSelectionKey()).thenReturn(selectionKey); - when(selectionKey.interestOps(anyInt())).thenThrow(cancelledKeyException); - socketSelector.preSelect(); - - verify(writeContext, times(0)).queueWriteOperations(writeOperation); - verify(listener).onFailure(cancelledKeyException); - } - - public void testQueueWriteSuccessful() throws Exception { - WriteOperation writeOperation = new WriteOperation(channel, bufferReference, listener); - socketSelector.queueWrite(writeOperation); - - assertTrue((selectionKey.interestOps() & SelectionKey.OP_WRITE) == 0); - - when(channel.isWritable()).thenReturn(true); - socketSelector.preSelect(); - - verify(writeContext).queueWriteOperations(writeOperation); - assertTrue((selectionKey.interestOps() & SelectionKey.OP_WRITE) != 0); - } - - public void testQueueDirectlyInChannelBufferSuccessful() throws Exception { - WriteOperation writeOperation = new WriteOperation(channel, bufferReference, listener); - - assertTrue((selectionKey.interestOps() & SelectionKey.OP_WRITE) == 0); - - when(channel.isWritable()).thenReturn(true); - socketSelector.queueWriteInChannelBuffer(writeOperation); - - verify(writeContext).queueWriteOperations(writeOperation); - assertTrue((selectionKey.interestOps() & SelectionKey.OP_WRITE) != 0); - } - - public void testQueueDirectlyInChannelBufferSelectionKeyThrowsException() throws Exception { - SelectionKey selectionKey = mock(SelectionKey.class); - - WriteOperation writeOperation = new WriteOperation(channel, bufferReference, listener); - CancelledKeyException cancelledKeyException = new CancelledKeyException(); - - when(channel.isWritable()).thenReturn(true); - when(channel.getSelectionKey()).thenReturn(selectionKey); - when(selectionKey.interestOps(anyInt())).thenThrow(cancelledKeyException); - socketSelector.queueWriteInChannelBuffer(writeOperation); - - verify(writeContext, times(0)).queueWriteOperations(writeOperation); - verify(listener).onFailure(cancelledKeyException); - } - - public void testConnectEvent() throws Exception { - selectionKey.setReadyOps(SelectionKey.OP_CONNECT); - - when(channel.finishConnect()).thenReturn(true); - socketSelector.processKey(selectionKey); - - verify(eventHandler).handleConnect(channel); - } - - public void testConnectEventFinishUnsuccessful() throws Exception { - selectionKey.setReadyOps(SelectionKey.OP_CONNECT); - - when(channel.finishConnect()).thenReturn(false); - socketSelector.processKey(selectionKey); - - verify(eventHandler, times(0)).handleConnect(channel); - } - - public void testConnectEventFinishThrowException() throws Exception { - IOException ioException = new IOException(); - - selectionKey.setReadyOps(SelectionKey.OP_CONNECT); - - when(channel.finishConnect()).thenThrow(ioException); - socketSelector.processKey(selectionKey); - - verify(eventHandler, times(0)).handleConnect(channel); - verify(eventHandler).connectException(channel, ioException); - } - - public void testWillNotConsiderWriteOrReadUntilConnectionComplete() throws Exception { - IOException ioException = new IOException(); - - selectionKey.setReadyOps(SelectionKey.OP_WRITE | SelectionKey.OP_READ); - - doThrow(ioException).when(eventHandler).handleWrite(channel); - - when(channel.isConnectComplete()).thenReturn(false); - socketSelector.processKey(selectionKey); - - verify(eventHandler, times(0)).handleWrite(channel); - verify(eventHandler, times(0)).handleRead(channel); - } - - public void testSuccessfulWriteEvent() throws Exception { - selectionKey.setReadyOps(SelectionKey.OP_WRITE); - - socketSelector.processKey(selectionKey); - - verify(eventHandler).handleWrite(channel); - } - - public void testWriteEventWithException() throws Exception { - IOException ioException = new IOException(); - - selectionKey.setReadyOps(SelectionKey.OP_WRITE); - - doThrow(ioException).when(eventHandler).handleWrite(channel); - - socketSelector.processKey(selectionKey); - - verify(eventHandler).writeException(channel, ioException); - } - - public void testSuccessfulReadEvent() throws Exception { - selectionKey.setReadyOps(SelectionKey.OP_READ); - - socketSelector.processKey(selectionKey); - - verify(eventHandler).handleRead(channel); - } - - public void testReadEventWithException() throws Exception { - IOException ioException = new IOException(); - - selectionKey.setReadyOps(SelectionKey.OP_READ); - - doThrow(ioException).when(eventHandler).handleRead(channel); - - socketSelector.processKey(selectionKey); - - verify(eventHandler).readException(channel, ioException); - } - - public void testCleanup() throws Exception { - NioSocketChannel unRegisteredChannel = mock(NioSocketChannel.class); - - socketSelector.scheduleForRegistration(channel); - - socketSelector.preSelect(); - - socketSelector.queueWrite(new WriteOperation(mock(NioSocketChannel.class), new BytesArray(new byte[1]), listener)); - socketSelector.scheduleForRegistration(unRegisteredChannel); - - TestSelectionKey testSelectionKey = new TestSelectionKey(0); - testSelectionKey.attach(channel); - when(rawSelector.keys()).thenReturn(new HashSet<>(Collections.singletonList(testSelectionKey))); - - socketSelector.cleanupAndCloseChannels(); - - verify(listener).onFailure(any(ClosedSelectorException.class)); - verify(eventHandler).handleClose(channel); - verify(eventHandler).handleClose(unRegisteredChannel); - } - - public void testExecuteListenerWillHandleException() throws Exception { - RuntimeException exception = new RuntimeException(); - doThrow(exception).when(listener).onResponse(null); - - socketSelector.executeListener(listener, null); - - verify(eventHandler).listenerException(listener, exception); - } - - public void testExecuteFailedListenerWillHandleException() throws Exception { - IOException ioException = new IOException(); - RuntimeException exception = new RuntimeException(); - doThrow(exception).when(listener).onFailure(ioException); - - socketSelector.executeFailedListener(listener, ioException); - - verify(eventHandler).listenerException(listener, exception); - } -} diff --git a/test/framework/src/test/java/org/elasticsearch/transport/nio/TestingSocketEventHandler.java b/test/framework/src/test/java/org/elasticsearch/transport/nio/TestingSocketEventHandler.java deleted file mode 100644 index a3cb92ad37663..0000000000000 --- a/test/framework/src/test/java/org/elasticsearch/transport/nio/TestingSocketEventHandler.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.apache.logging.log4j.Logger; -import org.elasticsearch.transport.nio.channel.NioSocketChannel; - -import java.io.IOException; -import java.util.Collections; -import java.util.Set; -import java.util.WeakHashMap; - -public class TestingSocketEventHandler extends SocketEventHandler { - - public TestingSocketEventHandler(Logger logger) { - super(logger); - } - - private Set hasConnectedMap = Collections.newSetFromMap(new WeakHashMap<>()); - - public void handleConnect(NioSocketChannel channel) { - assert hasConnectedMap.contains(channel) == false : "handleConnect should only be called once per channel"; - hasConnectedMap.add(channel); - super.handleConnect(channel); - } - - private Set hasConnectExceptionMap = Collections.newSetFromMap(new WeakHashMap<>()); - - public void connectException(NioSocketChannel channel, Exception e) { - assert hasConnectExceptionMap.contains(channel) == false : "connectException should only called at maximum once per channel"; - hasConnectExceptionMap.add(channel); - super.connectException(channel, e); - } - - public void handleRead(NioSocketChannel channel) throws IOException { - super.handleRead(channel); - } - - public void readException(NioSocketChannel channel, Exception e) { - super.readException(channel, e); - } - - public void handleWrite(NioSocketChannel channel) throws IOException { - super.handleWrite(channel); - } - - public void writeException(NioSocketChannel channel, Exception e) { - super.writeException(channel, e); - } - -} diff --git a/test/framework/src/test/java/org/elasticsearch/transport/nio/WriteOperationTests.java b/test/framework/src/test/java/org/elasticsearch/transport/nio/WriteOperationTests.java deleted file mode 100644 index 0085a9b204a31..0000000000000 --- a/test/framework/src/test/java/org/elasticsearch/transport/nio/WriteOperationTests.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio; - -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.common.bytes.BytesArray; -import org.elasticsearch.common.bytes.CompositeBytesReference; -import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.transport.nio.channel.NioSocketChannel; -import org.junit.Before; -import org.mockito.ArgumentCaptor; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.List; - -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class WriteOperationTests extends ESTestCase { - - private NioSocketChannel channel; - private ActionListener listener; - - @Before - @SuppressWarnings("unchecked") - public void setFields() { - channel = mock(NioSocketChannel.class); - listener = mock(ActionListener.class); - - } - - public void testFlush() throws IOException { - WriteOperation writeOp = new WriteOperation(channel, new BytesArray(new byte[10]), listener); - - - when(channel.write(any(ByteBuffer[].class))).thenReturn(10); - - writeOp.flush(); - - assertTrue(writeOp.isFullyFlushed()); - } - - public void testPartialFlush() throws IOException { - WriteOperation writeOp = new WriteOperation(channel, new BytesArray(new byte[10]), listener); - - when(channel.write(any(ByteBuffer[].class))).thenReturn(5); - - writeOp.flush(); - - assertFalse(writeOp.isFullyFlushed()); - } - - public void testMultipleFlushesWithCompositeBuffer() throws IOException { - BytesArray bytesReference1 = new BytesArray(new byte[10]); - BytesArray bytesReference2 = new BytesArray(new byte[15]); - BytesArray bytesReference3 = new BytesArray(new byte[3]); - CompositeBytesReference bytesReference = new CompositeBytesReference(bytesReference1, bytesReference2, bytesReference3); - WriteOperation writeOp = new WriteOperation(channel, bytesReference, listener); - - ArgumentCaptor buffersCaptor = ArgumentCaptor.forClass(ByteBuffer[].class); - - when(channel.write(buffersCaptor.capture())).thenReturn(5) - .thenReturn(5) - .thenReturn(2) - .thenReturn(15) - .thenReturn(1); - - writeOp.flush(); - assertFalse(writeOp.isFullyFlushed()); - writeOp.flush(); - assertFalse(writeOp.isFullyFlushed()); - writeOp.flush(); - assertFalse(writeOp.isFullyFlushed()); - writeOp.flush(); - assertFalse(writeOp.isFullyFlushed()); - writeOp.flush(); - assertTrue(writeOp.isFullyFlushed()); - - List values = buffersCaptor.getAllValues(); - ByteBuffer[] byteBuffers = values.get(0); - assertEquals(3, byteBuffers.length); - assertEquals(10, byteBuffers[0].remaining()); - - byteBuffers = values.get(1); - assertEquals(3, byteBuffers.length); - assertEquals(5, byteBuffers[0].remaining()); - - byteBuffers = values.get(2); - assertEquals(2, byteBuffers.length); - assertEquals(15, byteBuffers[0].remaining()); - - byteBuffers = values.get(3); - assertEquals(2, byteBuffers.length); - assertEquals(13, byteBuffers[0].remaining()); - - byteBuffers = values.get(4); - assertEquals(1, byteBuffers.length); - assertEquals(1, byteBuffers[0].remaining()); - } -} diff --git a/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/ChannelFactoryTests.java b/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/ChannelFactoryTests.java deleted file mode 100644 index 2f4c619dcb237..0000000000000 --- a/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/ChannelFactoryTests.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import org.elasticsearch.core.internal.io.IOUtils; -import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.transport.nio.AcceptingSelector; -import org.elasticsearch.transport.nio.SocketSelector; -import org.junit.After; -import org.junit.Before; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.nio.channels.ServerSocketChannel; -import java.nio.channels.SocketChannel; -import java.util.function.BiConsumer; - -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.same; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class ChannelFactoryTests extends ESTestCase { - - private ChannelFactory channelFactory; - private ChannelFactory.RawChannelFactory rawChannelFactory; - private SocketChannel rawChannel; - private ServerSocketChannel rawServerChannel; - private SocketSelector socketSelector; - private AcceptingSelector acceptingSelector; - - @Before - @SuppressWarnings("unchecked") - public void setupFactory() throws IOException { - rawChannelFactory = mock(TcpChannelFactory.RawChannelFactory.class); - channelFactory = new TestChannelFactory(rawChannelFactory); - socketSelector = mock(SocketSelector.class); - acceptingSelector = mock(AcceptingSelector.class); - rawChannel = SocketChannel.open(); - rawServerChannel = ServerSocketChannel.open(); - } - - @After - public void ensureClosed() throws IOException { - IOUtils.closeWhileHandlingException(rawChannel); - IOUtils.closeWhileHandlingException(rawServerChannel); - } - - public void testAcceptChannel() throws IOException { - NioServerSocketChannel serverChannel = mock(NioServerSocketChannel.class); - when(rawChannelFactory.acceptNioChannel(serverChannel)).thenReturn(rawChannel); - - NioSocketChannel channel = channelFactory.acceptNioChannel(serverChannel, socketSelector); - - verify(socketSelector).scheduleForRegistration(channel); - - assertEquals(socketSelector, channel.getSelector()); - assertEquals(rawChannel, channel.getRawChannel()); - } - - public void testAcceptedChannelRejected() throws IOException { - NioServerSocketChannel serverChannel = mock(NioServerSocketChannel.class); - when(rawChannelFactory.acceptNioChannel(serverChannel)).thenReturn(rawChannel); - doThrow(new IllegalStateException()).when(socketSelector).scheduleForRegistration(any()); - - expectThrows(IllegalStateException.class, () -> channelFactory.acceptNioChannel(serverChannel, socketSelector)); - - assertFalse(rawChannel.isOpen()); - } - - public void testOpenChannel() throws IOException { - InetSocketAddress address = mock(InetSocketAddress.class); - when(rawChannelFactory.openNioChannel(same(address))).thenReturn(rawChannel); - - NioSocketChannel channel = channelFactory.openNioChannel(address, socketSelector); - - verify(socketSelector).scheduleForRegistration(channel); - - assertEquals(socketSelector, channel.getSelector()); - assertEquals(rawChannel, channel.getRawChannel()); - } - - public void testOpenedChannelRejected() throws IOException { - InetSocketAddress address = mock(InetSocketAddress.class); - when(rawChannelFactory.openNioChannel(same(address))).thenReturn(rawChannel); - doThrow(new IllegalStateException()).when(socketSelector).scheduleForRegistration(any()); - - expectThrows(IllegalStateException.class, () -> channelFactory.openNioChannel(address, socketSelector)); - - assertFalse(rawChannel.isOpen()); - } - - public void testOpenServerChannel() throws IOException { - InetSocketAddress address = mock(InetSocketAddress.class); - when(rawChannelFactory.openNioServerSocketChannel(same(address))).thenReturn(rawServerChannel); - - NioServerSocketChannel channel = channelFactory.openNioServerSocketChannel(address, acceptingSelector); - - verify(acceptingSelector).scheduleForRegistration(channel); - - assertEquals(acceptingSelector, channel.getSelector()); - assertEquals(rawServerChannel, channel.getRawChannel()); - } - - public void testOpenedServerChannelRejected() throws IOException { - InetSocketAddress address = mock(InetSocketAddress.class); - when(rawChannelFactory.openNioServerSocketChannel(same(address))).thenReturn(rawServerChannel); - doThrow(new IllegalStateException()).when(acceptingSelector).scheduleForRegistration(any()); - - expectThrows(IllegalStateException.class, () -> channelFactory.openNioServerSocketChannel(address, acceptingSelector)); - - assertFalse(rawServerChannel.isOpen()); - } - - private static class TestChannelFactory extends ChannelFactory { - - TestChannelFactory(RawChannelFactory rawChannelFactory) { - super(rawChannelFactory); - } - - @SuppressWarnings("unchecked") - @Override - public NioSocketChannel createChannel(SocketSelector selector, SocketChannel channel) throws IOException { - NioSocketChannel nioSocketChannel = new NioSocketChannel(channel, selector); - nioSocketChannel.setContexts(mock(ReadContext.class), mock(WriteContext.class), mock(BiConsumer.class)); - return nioSocketChannel; - } - - @Override - public NioServerSocketChannel createServerChannel(AcceptingSelector selector, ServerSocketChannel channel) throws IOException { - return new NioServerSocketChannel(channel, this, selector); - } - } -} diff --git a/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/DoNotRegisterChannel.java b/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/DoNotRegisterChannel.java deleted file mode 100644 index f1f6ffb9f1138..0000000000000 --- a/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/DoNotRegisterChannel.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import org.elasticsearch.transport.nio.SocketSelector; -import org.elasticsearch.transport.nio.utils.TestSelectionKey; - -import java.io.IOException; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.SocketChannel; - -public class DoNotRegisterChannel extends NioSocketChannel { - - public DoNotRegisterChannel(SocketChannel socketChannel, SocketSelector selector) throws IOException { - super(socketChannel, selector); - } - - @Override - public void register() throws ClosedChannelException { - setSelectionKey(new TestSelectionKey(0)); - } -} diff --git a/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/DoNotRegisterServerChannel.java b/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/DoNotRegisterServerChannel.java deleted file mode 100644 index 073f2acf384da..0000000000000 --- a/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/DoNotRegisterServerChannel.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import org.elasticsearch.transport.nio.AcceptingSelector; -import org.elasticsearch.transport.nio.utils.TestSelectionKey; - -import java.io.IOException; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.ServerSocketChannel; - -public class DoNotRegisterServerChannel extends NioServerSocketChannel { - - public DoNotRegisterServerChannel(ServerSocketChannel channel, ChannelFactory channelFactory, AcceptingSelector selector) - throws IOException { - super(channel, channelFactory, selector); - } - - @Override - public void register() throws ClosedChannelException { - setSelectionKey(new TestSelectionKey(0)); - } -} diff --git a/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/NioServerSocketChannelTests.java b/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/NioServerSocketChannelTests.java deleted file mode 100644 index ba5d47fe8f8dd..0000000000000 --- a/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/NioServerSocketChannelTests.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.action.support.PlainActionFuture; -import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.transport.nio.AcceptingSelector; -import org.elasticsearch.transport.nio.AcceptorEventHandler; -import org.junit.After; -import org.junit.Before; - -import java.io.IOException; -import java.nio.channels.ServerSocketChannel; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Supplier; - -import static org.mockito.Mockito.mock; - -public class NioServerSocketChannelTests extends ESTestCase { - - private AcceptingSelector selector; - private AtomicBoolean closedRawChannel; - private Thread thread; - - @Before - @SuppressWarnings("unchecked") - public void setSelector() throws IOException { - selector = new AcceptingSelector(new AcceptorEventHandler(logger, mock(Supplier.class))); - thread = new Thread(selector::runLoop); - closedRawChannel = new AtomicBoolean(false); - thread.start(); - selector.isRunningFuture().actionGet(); - } - - @After - public void stopSelector() throws IOException, InterruptedException { - selector.close(); - thread.join(); - } - - public void testClose() throws Exception { - AtomicBoolean isClosed = new AtomicBoolean(false); - CountDownLatch latch = new CountDownLatch(1); - - NioChannel channel = new DoNotCloseServerChannel("nio", mock(ServerSocketChannel.class), mock(ChannelFactory.class), selector); - - channel.addCloseListener(new ActionListener() { - @Override - public void onResponse(Void o) { - isClosed.set(true); - latch.countDown(); - } - - @Override - public void onFailure(Exception e) { - isClosed.set(true); - latch.countDown(); - } - }); - - assertTrue(channel.isOpen()); - assertFalse(closedRawChannel.get()); - assertFalse(isClosed.get()); - - PlainActionFuture closeFuture = PlainActionFuture.newFuture(); - channel.addCloseListener(closeFuture); - channel.close(); - closeFuture.actionGet(); - - - assertTrue(closedRawChannel.get()); - assertFalse(channel.isOpen()); - latch.await(); - assertTrue(isClosed.get()); - } - - private class DoNotCloseServerChannel extends DoNotRegisterServerChannel { - - private DoNotCloseServerChannel(String profile, ServerSocketChannel channel, ChannelFactory channelFactory, - AcceptingSelector selector) throws IOException { - super(channel, channelFactory, selector); - } - - @Override - void closeRawChannel() throws IOException { - closedRawChannel.set(true); - } - } -} diff --git a/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/NioSocketChannelTests.java b/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/NioSocketChannelTests.java deleted file mode 100644 index fecaf8fe9701e..0000000000000 --- a/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/NioSocketChannelTests.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.action.support.PlainActionFuture; -import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.transport.nio.SocketEventHandler; -import org.elasticsearch.transport.nio.SocketSelector; -import org.junit.After; -import org.junit.Before; - -import java.io.IOException; -import java.net.ConnectException; -import java.nio.channels.SocketChannel; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.BiConsumer; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class NioSocketChannelTests extends ESTestCase { - - private SocketSelector selector; - private AtomicBoolean closedRawChannel; - private Thread thread; - - @Before - @SuppressWarnings("unchecked") - public void startSelector() throws IOException { - selector = new SocketSelector(new SocketEventHandler(logger)); - thread = new Thread(selector::runLoop); - closedRawChannel = new AtomicBoolean(false); - thread.start(); - selector.isRunningFuture().actionGet(); - } - - @After - public void stopSelector() throws IOException, InterruptedException { - selector.close(); - thread.join(); - } - - @SuppressWarnings("unchecked") - public void testClose() throws Exception { - AtomicBoolean isClosed = new AtomicBoolean(false); - CountDownLatch latch = new CountDownLatch(1); - - NioSocketChannel socketChannel = new DoNotCloseChannel(mock(SocketChannel.class), selector); - socketChannel.setContexts(mock(ReadContext.class), mock(WriteContext.class), mock(BiConsumer.class)); - socketChannel.addCloseListener(new ActionListener() { - @Override - public void onResponse(Void o) { - isClosed.set(true); - latch.countDown(); - } - @Override - public void onFailure(Exception e) { - isClosed.set(true); - latch.countDown(); - } - }); - - assertTrue(socketChannel.isOpen()); - assertFalse(closedRawChannel.get()); - assertFalse(isClosed.get()); - - PlainActionFuture closeFuture = PlainActionFuture.newFuture(); - socketChannel.addCloseListener(closeFuture); - socketChannel.close(); - closeFuture.actionGet(); - - assertTrue(closedRawChannel.get()); - assertFalse(socketChannel.isOpen()); - latch.await(); - assertTrue(isClosed.get()); - } - - @SuppressWarnings("unchecked") - public void testConnectSucceeds() throws Exception { - SocketChannel rawChannel = mock(SocketChannel.class); - when(rawChannel.finishConnect()).thenReturn(true); - NioSocketChannel socketChannel = new DoNotCloseChannel(rawChannel, selector); - socketChannel.setContexts(mock(ReadContext.class), mock(WriteContext.class), mock(BiConsumer.class)); - selector.scheduleForRegistration(socketChannel); - - PlainActionFuture connectFuture = PlainActionFuture.newFuture(); - socketChannel.addConnectListener(connectFuture); - connectFuture.get(100, TimeUnit.SECONDS); - - assertTrue(socketChannel.isConnectComplete()); - assertTrue(socketChannel.isOpen()); - assertFalse(closedRawChannel.get()); - } - - @SuppressWarnings("unchecked") - public void testConnectFails() throws Exception { - SocketChannel rawChannel = mock(SocketChannel.class); - when(rawChannel.finishConnect()).thenThrow(new ConnectException()); - NioSocketChannel socketChannel = new DoNotCloseChannel(rawChannel, selector); - socketChannel.setContexts(mock(ReadContext.class), mock(WriteContext.class), mock(BiConsumer.class)); - selector.scheduleForRegistration(socketChannel); - - PlainActionFuture connectFuture = PlainActionFuture.newFuture(); - socketChannel.addConnectListener(connectFuture); - ExecutionException e = expectThrows(ExecutionException.class, () -> connectFuture.get(100, TimeUnit.SECONDS)); - assertTrue(e.getCause() instanceof IOException); - - assertFalse(socketChannel.isConnectComplete()); - // Even if connection fails the channel is 'open' until close() is called - assertTrue(socketChannel.isOpen()); - } - - private class DoNotCloseChannel extends DoNotRegisterChannel { - - private DoNotCloseChannel(SocketChannel channel, SocketSelector selector) throws IOException { - super(channel, selector); - } - - @Override - void closeRawChannel() throws IOException { - closedRawChannel.set(true); - } - } -} diff --git a/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/TcpFrameDecoderTests.java b/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/TcpFrameDecoderTests.java deleted file mode 100644 index 450016b1dc3b8..0000000000000 --- a/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/TcpFrameDecoderTests.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.common.io.stream.BytesStreamOutput; -import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.transport.TcpTransport; - -import java.io.IOException; -import java.io.StreamCorruptedException; - -import static org.hamcrest.Matchers.instanceOf; - -public class TcpFrameDecoderTests extends ESTestCase { - - private TcpFrameDecoder frameDecoder = new TcpFrameDecoder(); - - public void testDefaultExceptedMessageLengthIsNegative1() { - assertEquals(-1, frameDecoder.expectedMessageLength()); - } - - public void testDecodeWithIncompleteHeader() throws IOException { - BytesStreamOutput streamOutput = new BytesStreamOutput(1 << 14); - streamOutput.write('E'); - streamOutput.write('S'); - streamOutput.write(1); - streamOutput.write(1); - - assertNull(frameDecoder.decode(streamOutput.bytes())); - assertEquals(-1, frameDecoder.expectedMessageLength()); - } - - public void testDecodePing() throws IOException { - BytesStreamOutput streamOutput = new BytesStreamOutput(1 << 14); - streamOutput.write('E'); - streamOutput.write('S'); - streamOutput.writeInt(-1); - - BytesReference message = frameDecoder.decode(streamOutput.bytes()); - - assertEquals(-1, frameDecoder.expectedMessageLength()); - assertEquals(streamOutput.bytes(), message); - } - - public void testDecodePingWithStartOfSecondMessage() throws IOException { - BytesStreamOutput streamOutput = new BytesStreamOutput(1 << 14); - streamOutput.write('E'); - streamOutput.write('S'); - streamOutput.writeInt(-1); - streamOutput.write('E'); - streamOutput.write('S'); - - BytesReference message = frameDecoder.decode(streamOutput.bytes()); - - assertEquals(6, message.length()); - assertEquals(streamOutput.bytes().slice(0, 6), message); - } - - public void testDecodeMessage() throws IOException { - BytesStreamOutput streamOutput = new BytesStreamOutput(1 << 14); - streamOutput.write('E'); - streamOutput.write('S'); - streamOutput.writeInt(2); - streamOutput.write('M'); - streamOutput.write('A'); - - BytesReference message = frameDecoder.decode(streamOutput.bytes()); - - assertEquals(-1, frameDecoder.expectedMessageLength()); - assertEquals(streamOutput.bytes(), message); - } - - public void testDecodeIncompleteMessage() throws IOException { - BytesStreamOutput streamOutput = new BytesStreamOutput(1 << 14); - streamOutput.write('E'); - streamOutput.write('S'); - streamOutput.writeInt(3); - streamOutput.write('M'); - streamOutput.write('A'); - - BytesReference message = frameDecoder.decode(streamOutput.bytes()); - - assertEquals(9, frameDecoder.expectedMessageLength()); - assertNull(message); - } - - public void testInvalidLength() throws IOException { - BytesStreamOutput streamOutput = new BytesStreamOutput(1 << 14); - streamOutput.write('E'); - streamOutput.write('S'); - streamOutput.writeInt(-2); - streamOutput.write('M'); - streamOutput.write('A'); - - try { - frameDecoder.decode(streamOutput.bytes()); - fail("Expected exception"); - } catch (Exception ex) { - assertThat(ex, instanceOf(StreamCorruptedException.class)); - assertEquals("invalid data length: -2", ex.getMessage()); - } - } - - public void testInvalidHeader() throws IOException { - BytesStreamOutput streamOutput = new BytesStreamOutput(1 << 14); - streamOutput.write('E'); - streamOutput.write('C'); - byte byte1 = randomByte(); - byte byte2 = randomByte(); - streamOutput.write(byte1); - streamOutput.write(byte2); - streamOutput.write(randomByte()); - streamOutput.write(randomByte()); - streamOutput.write(randomByte()); - - try { - frameDecoder.decode(streamOutput.bytes()); - fail("Expected exception"); - } catch (Exception ex) { - assertThat(ex, instanceOf(StreamCorruptedException.class)); - String expected = "invalid internal transport message format, got (45,43," - + Integer.toHexString(byte1 & 0xFF) + "," - + Integer.toHexString(byte2 & 0xFF) + ")"; - assertEquals(expected, ex.getMessage()); - } - } - - public void testHTTPHeader() throws IOException { - String[] httpHeaders = {"GET", "POST", "PUT", "HEAD", "DELETE", "OPTIONS", "PATCH", "TRACE"}; - - for (String httpHeader : httpHeaders) { - BytesStreamOutput streamOutput = new BytesStreamOutput(1 << 14); - - for (char c : httpHeader.toCharArray()) { - streamOutput.write((byte) c); - } - streamOutput.write(new byte[6]); - - try { - BytesReference bytes = streamOutput.bytes(); - frameDecoder.decode(bytes); - fail("Expected exception"); - } catch (Exception ex) { - assertThat(ex, instanceOf(TcpTransport.HttpOnTransportException.class)); - assertEquals("This is not a HTTP port", ex.getMessage()); - } - } - } -} diff --git a/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/TcpReadContextTests.java b/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/TcpReadContextTests.java deleted file mode 100644 index f24c087e60a30..0000000000000 --- a/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/TcpReadContextTests.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import org.elasticsearch.common.bytes.BytesArray; -import org.elasticsearch.common.bytes.CompositeBytesReference; -import org.elasticsearch.common.util.BigArrays; -import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.transport.nio.InboundChannelBuffer; -import org.elasticsearch.transport.nio.TcpReadHandler; -import org.junit.Before; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Supplier; - -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -public class TcpReadContextTests extends ESTestCase { - - private TcpReadHandler handler; - private int messageLength; - private TcpNioSocketChannel channel; - private TcpReadContext readContext; - - @Before - public void init() { - handler = mock(TcpReadHandler.class); - - messageLength = randomInt(96) + 4; - channel = mock(TcpNioSocketChannel.class); - Supplier pageSupplier = () -> - new InboundChannelBuffer.Page(ByteBuffer.allocate(BigArrays.BYTE_PAGE_SIZE), () -> {}); - readContext = new TcpReadContext(channel, handler, new InboundChannelBuffer(pageSupplier)); - } - - public void testSuccessfulRead() throws IOException { - byte[] bytes = createMessage(messageLength); - byte[] fullMessage = combineMessageAndHeader(bytes); - - final AtomicLong bufferCapacity = new AtomicLong(); - when(channel.read(any(InboundChannelBuffer.class))).thenAnswer(invocationOnMock -> { - InboundChannelBuffer buffer = (InboundChannelBuffer) invocationOnMock.getArguments()[0]; - ByteBuffer byteBuffer = buffer.sliceBuffersFrom(buffer.getIndex())[0]; - bufferCapacity.set(buffer.getCapacity() - buffer.getIndex()); - byteBuffer.put(fullMessage); - buffer.incrementIndex(fullMessage.length); - return fullMessage.length; - }); - - readContext.read(); - - verify(handler).handleMessage(new BytesArray(bytes), channel, messageLength); - assertEquals(1024 * 16, bufferCapacity.get()); - - BytesArray bytesArray = new BytesArray(new byte[10]); - bytesArray.slice(5, 5); - bytesArray.slice(5, 0); - } - - public void testPartialRead() throws IOException { - byte[] part1 = createMessage(messageLength); - byte[] fullPart1 = combineMessageAndHeader(part1, messageLength + messageLength); - byte[] part2 = createMessage(messageLength); - - final AtomicLong bufferCapacity = new AtomicLong(); - final AtomicReference bytes = new AtomicReference<>(); - - when(channel.read(any(InboundChannelBuffer.class))).thenAnswer(invocationOnMock -> { - InboundChannelBuffer buffer = (InboundChannelBuffer) invocationOnMock.getArguments()[0]; - ByteBuffer byteBuffer = buffer.sliceBuffersFrom(buffer.getIndex())[0]; - bufferCapacity.set(buffer.getCapacity() - buffer.getIndex()); - byteBuffer.put(bytes.get()); - buffer.incrementIndex(bytes.get().length); - return bytes.get().length; - }); - - - bytes.set(fullPart1); - readContext.read(); - - assertEquals(1024 * 16, bufferCapacity.get()); - verifyZeroInteractions(handler); - - bytes.set(part2); - readContext.read(); - - assertEquals(1024 * 16 - fullPart1.length, bufferCapacity.get()); - - CompositeBytesReference reference = new CompositeBytesReference(new BytesArray(part1), new BytesArray(part2)); - verify(handler).handleMessage(reference, channel, messageLength + messageLength); - } - - public void testReadThrowsIOException() throws IOException { - IOException ioException = new IOException(); - when(channel.read(any())).thenThrow(ioException); - - try { - readContext.read(); - fail("Expected exception"); - } catch (Exception ex) { - assertSame(ioException, ex); - } - } - - public void closeClosesChannelBuffer() { - InboundChannelBuffer buffer = mock(InboundChannelBuffer.class); - TcpReadContext readContext = new TcpReadContext(channel, handler, buffer); - - readContext.close(); - - verify(buffer).close(); - } - - private static byte[] combineMessageAndHeader(byte[] bytes) { - return combineMessageAndHeader(bytes, bytes.length); - } - - private static byte[] combineMessageAndHeader(byte[] bytes, int messageLength) { - byte[] fullMessage = new byte[bytes.length + 6]; - ByteBuffer wrapped = ByteBuffer.wrap(fullMessage); - wrapped.put((byte) 'E'); - wrapped.put((byte) 'S'); - wrapped.putInt(messageLength); - wrapped.put(bytes); - return fullMessage; - } - - private static byte[] createMessage(int length) { - byte[] bytes = new byte[length]; - for (int i = 0; i < length; ++i) { - bytes[i] = randomByte(); - } - return bytes; - } -} diff --git a/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/TcpWriteContextTests.java b/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/TcpWriteContextTests.java deleted file mode 100644 index 33b84590aaa51..0000000000000 --- a/test/framework/src/test/java/org/elasticsearch/transport/nio/channel/TcpWriteContextTests.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.channel; - -import org.elasticsearch.action.ActionListener; -import org.elasticsearch.common.bytes.BytesArray; -import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.transport.nio.SocketSelector; -import org.elasticsearch.transport.nio.WriteOperation; -import org.junit.Before; -import org.mockito.ArgumentCaptor; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.ClosedChannelException; - -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class TcpWriteContextTests extends ESTestCase { - - private SocketSelector selector; - private ActionListener listener; - private TcpWriteContext writeContext; - private NioSocketChannel channel; - - @Before - @SuppressWarnings("unchecked") - public void setUp() throws Exception { - super.setUp(); - selector = mock(SocketSelector.class); - listener = mock(ActionListener.class); - channel = mock(NioSocketChannel.class); - writeContext = new TcpWriteContext(channel); - - when(channel.getSelector()).thenReturn(selector); - when(selector.isOnCurrentThread()).thenReturn(true); - } - - public void testWriteFailsIfChannelNotWritable() throws Exception { - when(channel.isWritable()).thenReturn(false); - - writeContext.sendMessage(new BytesArray(generateBytes(10)), listener); - - verify(listener).onFailure(any(ClosedChannelException.class)); - } - - public void testSendMessageFromDifferentThreadIsQueuedWithSelector() throws Exception { - byte[] bytes = generateBytes(10); - BytesArray bytesArray = new BytesArray(bytes); - ArgumentCaptor writeOpCaptor = ArgumentCaptor.forClass(WriteOperation.class); - - when(selector.isOnCurrentThread()).thenReturn(false); - when(channel.isWritable()).thenReturn(true); - - writeContext.sendMessage(bytesArray, listener); - - verify(selector).queueWrite(writeOpCaptor.capture()); - WriteOperation writeOp = writeOpCaptor.getValue(); - - assertSame(listener, writeOp.getListener()); - assertSame(channel, writeOp.getChannel()); - assertEquals(ByteBuffer.wrap(bytes), writeOp.getByteBuffers()[0]); - } - - public void testSendMessageFromSameThreadIsQueuedInChannel() throws Exception { - byte[] bytes = generateBytes(10); - BytesArray bytesArray = new BytesArray(bytes); - ArgumentCaptor writeOpCaptor = ArgumentCaptor.forClass(WriteOperation.class); - - when(channel.isWritable()).thenReturn(true); - - writeContext.sendMessage(bytesArray, listener); - - verify(selector).queueWriteInChannelBuffer(writeOpCaptor.capture()); - WriteOperation writeOp = writeOpCaptor.getValue(); - - assertSame(listener, writeOp.getListener()); - assertSame(channel, writeOp.getChannel()); - assertEquals(ByteBuffer.wrap(bytes), writeOp.getByteBuffers()[0]); - } - - public void testWriteIsQueuedInChannel() throws Exception { - assertFalse(writeContext.hasQueuedWriteOps()); - - writeContext.queueWriteOperations(new WriteOperation(channel, new BytesArray(generateBytes(10)), listener)); - - assertTrue(writeContext.hasQueuedWriteOps()); - } - - public void testWriteOpsCanBeCleared() throws Exception { - assertFalse(writeContext.hasQueuedWriteOps()); - - writeContext.queueWriteOperations(new WriteOperation(channel, new BytesArray(generateBytes(10)), listener)); - - assertTrue(writeContext.hasQueuedWriteOps()); - - ClosedChannelException e = new ClosedChannelException(); - writeContext.clearQueuedWriteOps(e); - - verify(selector).executeFailedListener(listener, e); - - assertFalse(writeContext.hasQueuedWriteOps()); - } - - public void testQueuedWriteIsFlushedInFlushCall() throws Exception { - assertFalse(writeContext.hasQueuedWriteOps()); - - WriteOperation writeOperation = mock(WriteOperation.class); - writeContext.queueWriteOperations(writeOperation); - - assertTrue(writeContext.hasQueuedWriteOps()); - - when(writeOperation.isFullyFlushed()).thenReturn(true); - when(writeOperation.getListener()).thenReturn(listener); - writeContext.flushChannel(); - - verify(writeOperation).flush(); - verify(selector).executeListener(listener, null); - assertFalse(writeContext.hasQueuedWriteOps()); - } - - public void testPartialFlush() throws IOException { - assertFalse(writeContext.hasQueuedWriteOps()); - - WriteOperation writeOperation = mock(WriteOperation.class); - writeContext.queueWriteOperations(writeOperation); - - assertTrue(writeContext.hasQueuedWriteOps()); - - when(writeOperation.isFullyFlushed()).thenReturn(false); - writeContext.flushChannel(); - - verify(listener, times(0)).onResponse(null); - assertTrue(writeContext.hasQueuedWriteOps()); - } - - @SuppressWarnings("unchecked") - public void testMultipleWritesPartialFlushes() throws IOException { - assertFalse(writeContext.hasQueuedWriteOps()); - - ActionListener listener2 = mock(ActionListener.class); - WriteOperation writeOperation1 = mock(WriteOperation.class); - WriteOperation writeOperation2 = mock(WriteOperation.class); - when(writeOperation1.getListener()).thenReturn(listener); - when(writeOperation2.getListener()).thenReturn(listener2); - writeContext.queueWriteOperations(writeOperation1); - writeContext.queueWriteOperations(writeOperation2); - - assertTrue(writeContext.hasQueuedWriteOps()); - - when(writeOperation1.isFullyFlushed()).thenReturn(true); - when(writeOperation2.isFullyFlushed()).thenReturn(false); - writeContext.flushChannel(); - - verify(selector).executeListener(listener, null); - verify(listener2, times(0)).onResponse(channel); - assertTrue(writeContext.hasQueuedWriteOps()); - - when(writeOperation2.isFullyFlushed()).thenReturn(true); - - writeContext.flushChannel(); - - verify(selector).executeListener(listener2, null); - assertFalse(writeContext.hasQueuedWriteOps()); - } - - public void testWhenIOExceptionThrownListenerIsCalled() throws IOException { - assertFalse(writeContext.hasQueuedWriteOps()); - - WriteOperation writeOperation = mock(WriteOperation.class); - writeContext.queueWriteOperations(writeOperation); - - assertTrue(writeContext.hasQueuedWriteOps()); - - IOException exception = new IOException(); - when(writeOperation.flush()).thenThrow(exception); - when(writeOperation.getListener()).thenReturn(listener); - expectThrows(IOException.class, () -> writeContext.flushChannel()); - - verify(selector).executeFailedListener(listener, exception); - assertFalse(writeContext.hasQueuedWriteOps()); - } - - private byte[] generateBytes(int n) { - n += 10; - byte[] bytes = new byte[n]; - for (int i = 0; i < n; ++i) { - bytes[i] = randomByte(); - } - return bytes; - } -} diff --git a/test/framework/src/test/java/org/elasticsearch/transport/nio/utils/TestSelectionKey.java b/test/framework/src/test/java/org/elasticsearch/transport/nio/utils/TestSelectionKey.java deleted file mode 100644 index 0f0011f15533b..0000000000000 --- a/test/framework/src/test/java/org/elasticsearch/transport/nio/utils/TestSelectionKey.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you 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 org.elasticsearch.transport.nio.utils; - -import java.nio.channels.SelectableChannel; -import java.nio.channels.SelectionKey; -import java.nio.channels.Selector; -import java.nio.channels.spi.AbstractSelectionKey; - -public class TestSelectionKey extends AbstractSelectionKey { - - private int ops = 0; - private int readyOps; - - public TestSelectionKey(int ops) { - this.ops = ops; - } - - @Override - public SelectableChannel channel() { - return null; - } - - @Override - public Selector selector() { - return null; - } - - @Override - public int interestOps() { - return ops; - } - - @Override - public SelectionKey interestOps(int ops) { - this.ops = ops; - return this; - } - - @Override - public int readyOps() { - return readyOps; - } - - public void setReadyOps(int readyOps) { - this.readyOps = readyOps; - } -}