Search in sources :

Example 1 with PlainActionFuture

use of org.elasticsearch.action.support.PlainActionFuture in project elasticsearch by elastic.

the class AbstractSimpleTransportTestCase method testConcurrentSendRespondAndDisconnect.

public void testConcurrentSendRespondAndDisconnect() throws BrokenBarrierException, InterruptedException {
    Set<Exception> sendingErrors = ConcurrentCollections.newConcurrentSet();
    Set<Exception> responseErrors = ConcurrentCollections.newConcurrentSet();
    serviceA.registerRequestHandler("test", TestRequest::new, randomBoolean() ? ThreadPool.Names.SAME : ThreadPool.Names.GENERIC, (request, channel) -> {
        try {
            channel.sendResponse(new TestResponse());
        } catch (Exception e) {
            logger.info("caught exception while responding", e);
            responseErrors.add(e);
        }
    });
    final TransportRequestHandler<TestRequest> ignoringRequestHandler = (request, channel) -> {
        try {
            channel.sendResponse(new TestResponse());
        } catch (Exception e) {
            // we don't really care what's going on B, we're testing through A
            logger.trace("caught exception while responding from node B", e);
        }
    };
    serviceB.registerRequestHandler("test", TestRequest::new, ThreadPool.Names.SAME, ignoringRequestHandler);
    int halfSenders = scaledRandomIntBetween(3, 10);
    final CyclicBarrier go = new CyclicBarrier(halfSenders * 2 + 1);
    final CountDownLatch done = new CountDownLatch(halfSenders * 2);
    for (int i = 0; i < halfSenders; i++) {
        // B senders just generated activity so serciveA can respond, we don't test what's going on there
        final int sender = i;
        threadPool.executor(ThreadPool.Names.GENERIC).execute(new AbstractRunnable() {

            @Override
            public void onFailure(Exception e) {
                logger.trace("caught exception while sending from B", e);
            }

            @Override
            protected void doRun() throws Exception {
                go.await();
                for (int iter = 0; iter < 10; iter++) {
                    PlainActionFuture<TestResponse> listener = new PlainActionFuture<>();
                    final String info = sender + "_B_" + iter;
                    serviceB.sendRequest(nodeA, "test", new TestRequest(info), new ActionListenerResponseHandler<>(listener, TestResponse::new));
                    try {
                        listener.actionGet();
                    } catch (Exception e) {
                        logger.trace((Supplier<?>) () -> new ParameterizedMessage("caught exception while sending to node {}", nodeA), e);
                    }
                }
            }

            @Override
            public void onAfter() {
                done.countDown();
            }
        });
    }
    for (int i = 0; i < halfSenders; i++) {
        final int sender = i;
        threadPool.executor(ThreadPool.Names.GENERIC).execute(new AbstractRunnable() {

            @Override
            public void onFailure(Exception e) {
                logger.error("unexpected error", e);
                sendingErrors.add(e);
            }

            @Override
            protected void doRun() throws Exception {
                go.await();
                for (int iter = 0; iter < 10; iter++) {
                    PlainActionFuture<TestResponse> listener = new PlainActionFuture<>();
                    final String info = sender + "_" + iter;
                    // capture now
                    final DiscoveryNode node = nodeB;
                    try {
                        serviceA.sendRequest(node, "test", new TestRequest(info), new ActionListenerResponseHandler<>(listener, TestResponse::new));
                        try {
                            listener.actionGet();
                        } catch (ConnectTransportException e) {
                        // ok!
                        } catch (Exception e) {
                            logger.error((Supplier<?>) () -> new ParameterizedMessage("caught exception while sending to node {}", node), e);
                            sendingErrors.add(e);
                        }
                    } catch (NodeNotConnectedException ex) {
                    // ok
                    }
                }
            }

            @Override
            public void onAfter() {
                done.countDown();
            }
        });
    }
    go.await();
    for (int i = 0; i <= 10; i++) {
        if (i % 3 == 0) {
            // simulate restart of nodeB
            serviceB.close();
            MockTransportService newService = buildService("TS_B_" + i, version1, null);
            newService.registerRequestHandler("test", TestRequest::new, ThreadPool.Names.SAME, ignoringRequestHandler);
            serviceB = newService;
            nodeB = newService.getLocalDiscoNode();
            serviceB.connectToNode(nodeA);
            serviceA.connectToNode(nodeB);
        } else if (serviceA.nodeConnected(nodeB)) {
            serviceA.disconnectFromNode(nodeB);
        } else {
            serviceA.connectToNode(nodeB);
        }
    }
    done.await();
    assertThat("found non connection errors while sending", sendingErrors, empty());
    assertThat("found non connection errors while responding", responseErrors, empty());
}
Also used : ElasticsearchException(org.elasticsearch.ElasticsearchException) StreamOutput(org.elasticsearch.common.io.stream.StreamOutput) Arrays(java.util.Arrays) BigArrays(org.elasticsearch.common.util.BigArrays) ConcurrentCollections(org.elasticsearch.common.util.concurrent.ConcurrentCollections) InetAddress(java.net.InetAddress) ServerSocket(java.net.ServerSocket) Settings(org.elasticsearch.common.settings.Settings) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) After(org.junit.After) Map(java.util.Map) ThreadPool(org.elasticsearch.threadpool.ThreadPool) CyclicBarrier(java.util.concurrent.CyclicBarrier) Matchers.notNullValue(org.hamcrest.Matchers.notNullValue) PlainActionFuture(org.elasticsearch.action.support.PlainActionFuture) Set(java.util.Set) InetSocketAddress(java.net.InetSocketAddress) Matchers.startsWith(org.hamcrest.Matchers.startsWith) UncheckedIOException(java.io.UncheckedIOException) Matchers.instanceOf(org.hamcrest.Matchers.instanceOf) CountDownLatch(java.util.concurrent.CountDownLatch) AbstractRunnable(org.elasticsearch.common.util.concurrent.AbstractRunnable) List(java.util.List) Version(org.elasticsearch.Version) TransportAddress(org.elasticsearch.common.transport.TransportAddress) Supplier(org.apache.logging.log4j.util.Supplier) Matchers.equalTo(org.hamcrest.Matchers.equalTo) Socket(java.net.Socket) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) AtomicReference(java.util.concurrent.atomic.AtomicReference) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) NetworkService(org.elasticsearch.common.network.NetworkService) ActionListenerResponseHandler(org.elasticsearch.action.ActionListenerResponseHandler) NoneCircuitBreakerService(org.elasticsearch.indices.breaker.NoneCircuitBreakerService) NamedWriteableRegistry(org.elasticsearch.common.io.stream.NamedWriteableRegistry) TimeValue(org.elasticsearch.common.unit.TimeValue) Node(org.elasticsearch.node.Node) ESTestCase(org.elasticsearch.test.ESTestCase) MockTransportService(org.elasticsearch.test.transport.MockTransportService) Before(org.junit.Before) Collections.emptyMap(java.util.Collections.emptyMap) TestThreadPool(org.elasticsearch.threadpool.TestThreadPool) Matchers.empty(org.hamcrest.Matchers.empty) Collections.emptySet(java.util.Collections.emptySet) Semaphore(java.util.concurrent.Semaphore) IOUtils(org.apache.lucene.util.IOUtils) IOException(java.io.IOException) BrokenBarrierException(java.util.concurrent.BrokenBarrierException) MockServerSocket(org.elasticsearch.mocksocket.MockServerSocket) VersionUtils(org.elasticsearch.test.VersionUtils) CollectionUtil(org.apache.lucene.util.CollectionUtil) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) ExceptionsHelper(org.elasticsearch.ExceptionsHelper) ClusterSettings(org.elasticsearch.common.settings.ClusterSettings) Constants(org.apache.lucene.util.Constants) StreamInput(org.elasticsearch.common.io.stream.StreamInput) Collections(java.util.Collections) AbstractRunnable(org.elasticsearch.common.util.concurrent.AbstractRunnable) DiscoveryNode(org.elasticsearch.cluster.node.DiscoveryNode) MockTransportService(org.elasticsearch.test.transport.MockTransportService) CountDownLatch(java.util.concurrent.CountDownLatch) ElasticsearchException(org.elasticsearch.ElasticsearchException) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) BrokenBarrierException(java.util.concurrent.BrokenBarrierException) ExecutionException(java.util.concurrent.ExecutionException) CyclicBarrier(java.util.concurrent.CyclicBarrier) PlainActionFuture(org.elasticsearch.action.support.PlainActionFuture) ActionListenerResponseHandler(org.elasticsearch.action.ActionListenerResponseHandler) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage)

Example 2 with PlainActionFuture

use of org.elasticsearch.action.support.PlainActionFuture in project elasticsearch by elastic.

the class TransportReplicationActionTests method testReplicaProxy.

public void testReplicaProxy() throws InterruptedException, ExecutionException {
    ReplicationOperation.Replicas proxy = action.newReplicasProxy();
    final String index = "test";
    final ShardId shardId = new ShardId(index, "_na_", 0);
    ClusterState state = stateWithActivePrimary(index, true, 1 + randomInt(3), randomInt(2));
    logger.info("using state: {}", state);
    setState(clusterService, state);
    // check that at unknown node fails
    PlainActionFuture<ReplicaResponse> listener = new PlainActionFuture<>();
    proxy.performOn(TestShardRouting.newShardRouting(shardId, "NOT THERE", false, randomFrom(ShardRoutingState.values())), new Request(), listener);
    assertTrue(listener.isDone());
    assertListenerThrows("non existent node should throw a NoNodeAvailableException", listener, NoNodeAvailableException.class);
    final IndexShardRoutingTable shardRoutings = state.routingTable().shardRoutingTable(shardId);
    final ShardRouting replica = randomFrom(shardRoutings.replicaShards().stream().filter(ShardRouting::assignedToNode).collect(Collectors.toList()));
    listener = new PlainActionFuture<>();
    proxy.performOn(replica, new Request(), listener);
    assertFalse(listener.isDone());
    CapturingTransport.CapturedRequest[] captures = transport.getCapturedRequestsAndClear();
    assertThat(captures, arrayWithSize(1));
    if (randomBoolean()) {
        final TransportReplicationAction.ReplicaResponse response = new TransportReplicationAction.ReplicaResponse(randomAsciiOfLength(10), randomLong());
        transport.handleResponse(captures[0].requestId, response);
        assertTrue(listener.isDone());
        assertThat(listener.get(), equalTo(response));
    } else if (randomBoolean()) {
        transport.handleRemoteError(captures[0].requestId, new ElasticsearchException("simulated"));
        assertTrue(listener.isDone());
        assertListenerThrows("listener should reflect remote error", listener, ElasticsearchException.class);
    } else {
        transport.handleError(captures[0].requestId, new TransportException("simulated"));
        assertTrue(listener.isDone());
        assertListenerThrows("listener should reflect remote error", listener, TransportException.class);
    }
    AtomicReference<Object> failure = new AtomicReference<>();
    AtomicReference<Object> ignoredFailure = new AtomicReference<>();
    AtomicBoolean success = new AtomicBoolean();
    proxy.failShardIfNeeded(replica, randomIntBetween(1, 10), "test", new ElasticsearchException("simulated"), () -> success.set(true), failure::set, ignoredFailure::set);
    CapturingTransport.CapturedRequest[] shardFailedRequests = transport.getCapturedRequestsAndClear();
    // A replication action doesn't not fail the request
    assertEquals(0, shardFailedRequests.length);
}
Also used : ClusterState(org.elasticsearch.cluster.ClusterState) IndexShardRoutingTable(org.elasticsearch.cluster.routing.IndexShardRoutingTable) TransportRequest(org.elasticsearch.transport.TransportRequest) CloseIndexRequest(org.elasticsearch.action.admin.indices.close.CloseIndexRequest) AtomicReference(java.util.concurrent.atomic.AtomicReference) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) Matchers.anyString(org.mockito.Matchers.anyString) ElasticsearchException(org.elasticsearch.ElasticsearchException) TransportException(org.elasticsearch.transport.TransportException) ShardId(org.elasticsearch.index.shard.ShardId) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) PlainActionFuture(org.elasticsearch.action.support.PlainActionFuture) ReplicaResponse(org.elasticsearch.action.support.replication.ReplicationOperation.ReplicaResponse) TestShardRouting(org.elasticsearch.cluster.routing.TestShardRouting) ShardRouting(org.elasticsearch.cluster.routing.ShardRouting)

Example 3 with PlainActionFuture

use of org.elasticsearch.action.support.PlainActionFuture in project elasticsearch by elastic.

the class TransportReplicationActionTests method testPrimaryPhaseExecutesOrDelegatesRequestToRelocationTarget.

public void testPrimaryPhaseExecutesOrDelegatesRequestToRelocationTarget() throws Exception {
    final String index = "test";
    final ShardId shardId = new ShardId(index, "_na_", 0);
    ClusterState state = stateWithActivePrimary(index, true, randomInt(5));
    setState(clusterService, state);
    Request request = new Request(shardId).timeout("1ms");
    PlainActionFuture<TestResponse> listener = new PlainActionFuture<>();
    ReplicationTask task = maybeTask();
    AtomicBoolean executed = new AtomicBoolean();
    ShardRouting primaryShard = state.getRoutingTable().shardRoutingTable(shardId).primaryShard();
    boolean executeOnPrimary = true;
    // whether shard has been marked as relocated already (i.e. relocation completed)
    if (primaryShard.relocating() && randomBoolean()) {
        isRelocated.set(true);
        executeOnPrimary = false;
    }
    action.new AsyncPrimaryAction(request, primaryShard.allocationId().getId(), createTransportChannel(listener), task) {

        @Override
        protected ReplicationOperation<Request, Request, TransportReplicationAction.PrimaryResult<Request, TestResponse>> createReplicatedOperation(Request request, ActionListener<TransportReplicationAction.PrimaryResult<Request, TestResponse>> actionListener, TransportReplicationAction<Request, Request, TestResponse>.PrimaryShardReference<Request, Request, TestResponse> primaryShardReference, boolean executeOnReplicas) {
            return new NoopReplicationOperation(request, actionListener) {

                public void execute() throws Exception {
                    assertPhase(task, "primary");
                    assertFalse(executed.getAndSet(true));
                    super.execute();
                }
            };
        }
    }.run();
    if (executeOnPrimary) {
        assertTrue(executed.get());
        assertTrue(listener.isDone());
        listener.get();
        assertPhase(task, "finished");
        assertFalse(request.isRetrySet.get());
    } else {
        assertFalse(executed.get());
        // it should have been freed.
        assertIndexShardCounter(0);
        final List<CapturingTransport.CapturedRequest> requests = transport.capturedRequestsByTargetNode().get(primaryShard.relocatingNodeId());
        assertThat(requests, notNullValue());
        assertThat(requests.size(), equalTo(1));
        assertThat("primary request was not delegated to relocation target", requests.get(0).action, equalTo("testAction[p]"));
        assertPhase(task, "primary_delegation");
        transport.handleResponse(requests.get(0).requestId, new TestResponse());
        assertTrue(listener.isDone());
        listener.get();
        assertPhase(task, "finished");
        assertFalse(request.isRetrySet.get());
    }
}
Also used : ClusterState(org.elasticsearch.cluster.ClusterState) TransportRequest(org.elasticsearch.transport.TransportRequest) CloseIndexRequest(org.elasticsearch.action.admin.indices.close.CloseIndexRequest) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) Matchers.anyString(org.mockito.Matchers.anyString) ElasticsearchException(org.elasticsearch.ElasticsearchException) AlreadyClosedException(org.apache.lucene.store.AlreadyClosedException) IndexClosedException(org.elasticsearch.indices.IndexClosedException) NodeClosedException(org.elasticsearch.node.NodeClosedException) ShardNotFoundException(org.elasticsearch.index.shard.ShardNotFoundException) IndexNotFoundException(org.elasticsearch.index.IndexNotFoundException) NoNodeAvailableException(org.elasticsearch.client.transport.NoNodeAvailableException) TransportException(org.elasticsearch.transport.TransportException) IndexShardClosedException(org.elasticsearch.index.shard.IndexShardClosedException) ClusterBlockException(org.elasticsearch.cluster.block.ClusterBlockException) IOException(java.io.IOException) UnavailableShardsException(org.elasticsearch.action.UnavailableShardsException) ExecutionException(java.util.concurrent.ExecutionException) ShardId(org.elasticsearch.index.shard.ShardId) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) PlainActionFuture(org.elasticsearch.action.support.PlainActionFuture) TestShardRouting(org.elasticsearch.cluster.routing.TestShardRouting) ShardRouting(org.elasticsearch.cluster.routing.ShardRouting)

Example 4 with PlainActionFuture

use of org.elasticsearch.action.support.PlainActionFuture in project elasticsearch by elastic.

the class TransportReplicationActionTests method testRoutePhaseExecutesRequest.

public void testRoutePhaseExecutesRequest() {
    final String index = "test";
    final ShardId shardId = new ShardId(index, "_na_", 0);
    ReplicationTask task = maybeTask();
    setState(clusterService, stateWithActivePrimary(index, randomBoolean(), 3));
    logger.debug("using state: \n{}", clusterService.state());
    final IndexShardRoutingTable shardRoutingTable = clusterService.state().routingTable().index(index).shard(shardId.id());
    final String primaryNodeId = shardRoutingTable.primaryShard().currentNodeId();
    Request request = new Request(shardId);
    PlainActionFuture<TestResponse> listener = new PlainActionFuture<>();
    TestAction.ReroutePhase reroutePhase = action.new ReroutePhase(task, request, listener);
    reroutePhase.run();
    assertThat(request.shardId(), equalTo(shardId));
    logger.info("--> primary is assigned to [{}], checking request forwarded", primaryNodeId);
    final List<CapturingTransport.CapturedRequest> capturedRequests = transport.getCapturedRequestsByTargetNodeAndClear().get(primaryNodeId);
    assertThat(capturedRequests, notNullValue());
    assertThat(capturedRequests.size(), equalTo(1));
    if (clusterService.state().nodes().getLocalNodeId().equals(primaryNodeId)) {
        assertThat(capturedRequests.get(0).action, equalTo("testAction[p]"));
        assertPhase(task, "waiting_on_primary");
    } else {
        assertThat(capturedRequests.get(0).action, equalTo("testAction"));
        assertPhase(task, "rerouted");
    }
    assertFalse(request.isRetrySet.get());
    assertIndexShardUninitialized();
}
Also used : IndexShardRoutingTable(org.elasticsearch.cluster.routing.IndexShardRoutingTable) TransportRequest(org.elasticsearch.transport.TransportRequest) CloseIndexRequest(org.elasticsearch.action.admin.indices.close.CloseIndexRequest) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) Matchers.anyString(org.mockito.Matchers.anyString) ShardId(org.elasticsearch.index.shard.ShardId) PlainActionFuture(org.elasticsearch.action.support.PlainActionFuture)

Example 5 with PlainActionFuture

use of org.elasticsearch.action.support.PlainActionFuture in project elasticsearch by elastic.

the class TransportReplicationActionTests method testStalePrimaryShardOnReroute.

public void testStalePrimaryShardOnReroute() throws InterruptedException {
    final String index = "test";
    final ShardId shardId = new ShardId(index, "_na_", 0);
    // no replicas in order to skip the replication part
    setState(clusterService, stateWithActivePrimary(index, true, randomInt(3)));
    logger.debug("--> using initial state:\n{}", clusterService.state());
    Request request = new Request(shardId);
    boolean timeout = randomBoolean();
    if (timeout) {
        request.timeout("0s");
    } else {
        request.timeout("1h");
    }
    PlainActionFuture<TestResponse> listener = new PlainActionFuture<>();
    ReplicationTask task = maybeTask();
    TestAction.ReroutePhase reroutePhase = action.new ReroutePhase(task, request, listener);
    reroutePhase.run();
    CapturingTransport.CapturedRequest[] capturedRequests = transport.getCapturedRequestsAndClear();
    assertThat(capturedRequests, arrayWithSize(1));
    assertThat(capturedRequests[0].action, equalTo("testAction[p]"));
    assertPhase(task, "waiting_on_primary");
    assertFalse(request.isRetrySet.get());
    transport.handleRemoteError(capturedRequests[0].requestId, randomRetryPrimaryException(shardId));
    if (timeout) {
        // we always try at least one more time on timeout
        assertThat(listener.isDone(), equalTo(false));
        capturedRequests = transport.getCapturedRequestsAndClear();
        assertThat(capturedRequests, arrayWithSize(1));
        assertThat(capturedRequests[0].action, equalTo("testAction[p]"));
        assertPhase(task, "waiting_on_primary");
        transport.handleRemoteError(capturedRequests[0].requestId, randomRetryPrimaryException(shardId));
        assertListenerThrows("must throw index not found exception", listener, ElasticsearchException.class);
        assertPhase(task, "failed");
    } else {
        assertThat(listener.isDone(), equalTo(false));
        // generate a CS change
        setState(clusterService, clusterService.state());
        capturedRequests = transport.getCapturedRequestsAndClear();
        assertThat(capturedRequests, arrayWithSize(1));
        assertThat(capturedRequests[0].action, equalTo("testAction[p]"));
    }
}
Also used : TransportRequest(org.elasticsearch.transport.TransportRequest) CloseIndexRequest(org.elasticsearch.action.admin.indices.close.CloseIndexRequest) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) Matchers.anyString(org.mockito.Matchers.anyString) ShardId(org.elasticsearch.index.shard.ShardId) PlainActionFuture(org.elasticsearch.action.support.PlainActionFuture)

Aggregations

PlainActionFuture (org.elasticsearch.action.support.PlainActionFuture)82 ShardId (org.elasticsearch.index.shard.ShardId)37 ClusterState (org.elasticsearch.cluster.ClusterState)28 ExecutionException (java.util.concurrent.ExecutionException)27 ShardRouting (org.elasticsearch.cluster.routing.ShardRouting)25 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)21 IOException (java.io.IOException)20 ArrayList (java.util.ArrayList)20 Test (org.junit.Test)20 IndexShardRoutingTable (org.elasticsearch.cluster.routing.IndexShardRoutingTable)18 ElasticsearchException (org.elasticsearch.ElasticsearchException)17 TransportRequest (org.elasticsearch.transport.TransportRequest)17 Matchers.anyString (org.mockito.Matchers.anyString)17 HashSet (java.util.HashSet)16 List (java.util.List)16 CloseIndexRequest (org.elasticsearch.action.admin.indices.close.CloseIndexRequest)16 IndexShard (org.elasticsearch.index.shard.IndexShard)16 CoreMatchers.containsString (org.hamcrest.CoreMatchers.containsString)16 DiscoveryNode (org.elasticsearch.cluster.node.DiscoveryNode)15 ClusterBlockException (org.elasticsearch.cluster.block.ClusterBlockException)13