Search in sources :

Example 11 with PlainActionFuture

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

the class ReplicationOperationTests method testDemotedPrimary.

public void testDemotedPrimary() throws Exception {
    final String index = "test";
    final ShardId shardId = new ShardId(index, "_na_", 0);
    ClusterState state = stateWithActivePrimary(index, true, 1 + randomInt(2), randomInt(2));
    IndexMetaData indexMetaData = state.getMetaData().index(index);
    final long primaryTerm = indexMetaData.primaryTerm(0);
    ShardRouting primaryShard = state.getRoutingTable().shardRoutingTable(shardId).primaryShard();
    if (primaryShard.relocating() && randomBoolean()) {
        // simulate execution of the replication phase on the relocation target node after relocation source was marked as relocated
        state = ClusterState.builder(state).nodes(DiscoveryNodes.builder(state.nodes()).localNodeId(primaryShard.relocatingNodeId())).build();
        primaryShard = primaryShard.getTargetRelocatingShard();
    }
    // add in-sync allocation id that doesn't have a corresponding routing entry
    state = ClusterState.builder(state).metaData(MetaData.builder(state.metaData()).put(IndexMetaData.builder(indexMetaData).putInSyncAllocationIds(0, Sets.union(indexMetaData.inSyncAllocationIds(0), Sets.newHashSet(randomAsciiOfLength(10)))))).build();
    final Set<ShardRouting> expectedReplicas = getExpectedReplicas(shardId, state);
    final Map<ShardRouting, Exception> expectedFailures = new HashMap<>();
    final ShardRouting failedReplica = randomFrom(new ArrayList<>(expectedReplicas));
    expectedFailures.put(failedReplica, new CorruptIndexException("simulated", (String) null));
    Request request = new Request(shardId);
    PlainActionFuture<TestPrimary.Result> listener = new PlainActionFuture<>();
    final ClusterState finalState = state;
    final boolean testPrimaryDemotedOnStaleShardCopies = randomBoolean();
    final TestReplicaProxy replicasProxy = new TestReplicaProxy(expectedFailures) {

        @Override
        public void failShardIfNeeded(ShardRouting replica, long primaryTerm, String message, Exception exception, Runnable onSuccess, Consumer<Exception> onPrimaryDemoted, Consumer<Exception> onIgnoredFailure) {
            if (testPrimaryDemotedOnStaleShardCopies) {
                super.failShardIfNeeded(replica, primaryTerm, message, exception, onSuccess, onPrimaryDemoted, onIgnoredFailure);
            } else {
                assertThat(replica, equalTo(failedReplica));
                onPrimaryDemoted.accept(new ElasticsearchException("the king is dead"));
            }
        }

        @Override
        public void markShardCopyAsStaleIfNeeded(ShardId shardId, String allocationId, long primaryTerm, Runnable onSuccess, Consumer<Exception> onPrimaryDemoted, Consumer<Exception> onIgnoredFailure) {
            if (testPrimaryDemotedOnStaleShardCopies) {
                onPrimaryDemoted.accept(new ElasticsearchException("the king is dead"));
            } else {
                super.markShardCopyAsStaleIfNeeded(shardId, allocationId, primaryTerm, onSuccess, onPrimaryDemoted, onIgnoredFailure);
            }
        }
    };
    AtomicBoolean primaryFailed = new AtomicBoolean();
    final TestPrimary primary = new TestPrimary(primaryShard, primaryTerm) {

        @Override
        public void failShard(String message, Exception exception) {
            assertTrue(primaryFailed.compareAndSet(false, true));
        }
    };
    final TestReplicationOperation op = new TestReplicationOperation(request, primary, listener, replicasProxy, () -> finalState);
    op.execute();
    assertThat("request was not processed on primary", request.processedOnPrimary.get(), equalTo(true));
    assertTrue("listener is not marked as done", listener.isDone());
    assertTrue(primaryFailed.get());
    assertListenerThrows("should throw exception to trigger retry", listener, ReplicationOperation.RetryOnPrimaryException.class);
}
Also used : HashMap(java.util.HashMap) ElasticsearchException(org.elasticsearch.ElasticsearchException) ShardId(org.elasticsearch.index.shard.ShardId) Consumer(java.util.function.Consumer) ClusterState(org.elasticsearch.cluster.ClusterState) CorruptIndexException(org.apache.lucene.index.CorruptIndexException) ElasticsearchException(org.elasticsearch.ElasticsearchException) CorruptIndexException(org.apache.lucene.index.CorruptIndexException) IndexShardNotStartedException(org.elasticsearch.index.shard.IndexShardNotStartedException) UnavailableShardsException(org.elasticsearch.action.UnavailableShardsException) ExecutionException(java.util.concurrent.ExecutionException) IndexMetaData(org.elasticsearch.cluster.metadata.IndexMetaData) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) PlainActionFuture(org.elasticsearch.action.support.PlainActionFuture) ShardRouting(org.elasticsearch.cluster.routing.ShardRouting)

Example 12 with PlainActionFuture

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

the class TransportReplicationActionTests method testCounterOnPrimary.

public void testCounterOnPrimary() throws Exception {
    final String index = "test";
    final ShardId shardId = new ShardId(index, "_na_", 0);
    // no replica, we only want to test on primary
    final ClusterState state = state(index, true, ShardRoutingState.STARTED);
    setState(clusterService, state);
    logger.debug("--> using initial state:\n{}", clusterService.state());
    final ShardRouting primaryShard = state.routingTable().shardRoutingTable(shardId).primaryShard();
    Request request = new Request(shardId);
    PlainActionFuture<TestResponse> listener = new PlainActionFuture<>();
    ReplicationTask task = maybeTask();
    int i = randomInt(3);
    final boolean throwExceptionOnCreation = i == 1;
    final boolean throwExceptionOnRun = i == 2;
    final boolean respondWithError = i == 3;
    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) {
            assertIndexShardCounter(1);
            if (throwExceptionOnCreation) {
                throw new ElasticsearchException("simulated exception, during createReplicatedOperation");
            }
            return new NoopReplicationOperation(request, actionListener) {

                @Override
                public void execute() throws Exception {
                    assertIndexShardCounter(1);
                    assertPhase(task, "primary");
                    if (throwExceptionOnRun) {
                        throw new ElasticsearchException("simulated exception, during performOnPrimary");
                    } else if (respondWithError) {
                        this.resultListener.onFailure(new ElasticsearchException("simulated exception, as a response"));
                    } else {
                        super.execute();
                    }
                }
            };
        }
    }.run();
    assertIndexShardCounter(0);
    assertTrue(listener.isDone());
    assertPhase(task, "finished");
    try {
        listener.get();
    } catch (ExecutionException e) {
        if (throwExceptionOnCreation || throwExceptionOnRun || respondWithError) {
            Throwable cause = e.getCause();
            assertThat(cause, instanceOf(ElasticsearchException.class));
            assertThat(cause.getMessage(), containsString("simulated"));
        } else {
            throw e;
        }
    }
}
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) 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) PlainActionFuture(org.elasticsearch.action.support.PlainActionFuture) TestShardRouting(org.elasticsearch.cluster.routing.TestShardRouting) ShardRouting(org.elasticsearch.cluster.routing.ShardRouting) ExecutionException(java.util.concurrent.ExecutionException)

Example 13 with PlainActionFuture

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

the class TransportReplicationActionTests method testRetryOnReplica.

/**
     * test throwing a {@link org.elasticsearch.action.support.replication.TransportReplicationAction.RetryOnReplicaException}
     * causes a retry
     */
public void testRetryOnReplica() throws Exception {
    final ShardId shardId = new ShardId("test", "_na_", 0);
    ClusterState state = state(shardId.getIndexName(), true, ShardRoutingState.STARTED, ShardRoutingState.STARTED);
    final ShardRouting replica = state.getRoutingTable().shardRoutingTable(shardId).replicaShards().get(0);
    // simulate execution of the node holding the replica
    state = ClusterState.builder(state).nodes(DiscoveryNodes.builder(state.nodes()).localNodeId(replica.currentNodeId())).build();
    setState(clusterService, state);
    AtomicBoolean throwException = new AtomicBoolean(true);
    final ReplicationTask task = maybeTask();
    TestAction action = new TestAction(Settings.EMPTY, "testActionWithExceptions", transportService, clusterService, shardStateAction, threadPool) {

        @Override
        protected ReplicaResult shardOperationOnReplica(Request request, IndexShard replica) {
            assertPhase(task, "replica");
            if (throwException.get()) {
                throw new RetryOnReplicaException(shardId, "simulation");
            }
            return new ReplicaResult();
        }
    };
    final TestAction.ReplicaOperationTransportHandler replicaOperationTransportHandler = action.new ReplicaOperationTransportHandler();
    final PlainActionFuture<TestResponse> listener = new PlainActionFuture<>();
    final Request request = new Request().setShardId(shardId);
    request.primaryTerm(state.metaData().getIndexSafe(shardId.getIndex()).primaryTerm(shardId.id()));
    replicaOperationTransportHandler.messageReceived(new TransportReplicationAction.ConcreteShardRequest<>(request, replica.allocationId().getId()), createTransportChannel(listener), task);
    if (listener.isDone()) {
        // fail with the exception if there
        listener.get();
        fail("listener shouldn't be done");
    }
    // no retry yet
    List<CapturingTransport.CapturedRequest> capturedRequests = transport.getCapturedRequestsByTargetNodeAndClear().get(replica.currentNodeId());
    assertThat(capturedRequests, nullValue());
    // release the waiting
    throwException.set(false);
    setState(clusterService, state);
    capturedRequests = transport.getCapturedRequestsByTargetNodeAndClear().get(replica.currentNodeId());
    assertThat(capturedRequests, notNullValue());
    assertThat(capturedRequests.size(), equalTo(1));
    final CapturingTransport.CapturedRequest capturedRequest = capturedRequests.get(0);
    assertThat(capturedRequest.action, equalTo("testActionWithExceptions[r]"));
    assertThat(capturedRequest.request, instanceOf(TransportReplicationAction.ConcreteShardRequest.class));
    assertConcreteShardRequest(capturedRequest.request, request, replica.allocationId());
}
Also used : ClusterState(org.elasticsearch.cluster.ClusterState) IndexShard(org.elasticsearch.index.shard.IndexShard) CapturingTransport(org.elasticsearch.test.transport.CapturingTransport) TransportRequest(org.elasticsearch.transport.TransportRequest) CloseIndexRequest(org.elasticsearch.action.admin.indices.close.CloseIndexRequest) 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 14 with PlainActionFuture

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

the class TransportWriteActionTests method testReplicaProxy.

public void testReplicaProxy() throws InterruptedException, ExecutionException {
    CapturingTransport transport = new CapturingTransport();
    TransportService transportService = new TransportService(clusterService.getSettings(), transport, threadPool, TransportService.NOOP_TRANSPORT_INTERCEPTOR, x -> clusterService.localNode(), null);
    transportService.start();
    transportService.acceptIncomingRequests();
    ShardStateAction shardStateAction = new ShardStateAction(Settings.EMPTY, clusterService, transportService, null, null, threadPool);
    TestAction action = action = new TestAction(Settings.EMPTY, "testAction", transportService, clusterService, shardStateAction, threadPool);
    ReplicationOperation.Replicas proxy = action.newReplicasProxy();
    final String index = "test";
    final ShardId shardId = new ShardId(index, "_na_", 0);
    ClusterState state = ClusterStateCreationUtils.stateWithActivePrimary(index, true, 1 + randomInt(3), randomInt(2));
    logger.info("using state: {}", state);
    ClusterServiceUtils.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 TestRequest(), 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 TestRequest(), 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 write replication action proxy should fail the shard
    assertEquals(1, shardFailedRequests.length);
    CapturingTransport.CapturedRequest shardFailedRequest = shardFailedRequests[0];
    ShardStateAction.ShardEntry shardEntry = (ShardStateAction.ShardEntry) shardFailedRequest.request;
    // the shard the request was sent to and the shard to be failed should be the same
    assertEquals(shardEntry.getShardId(), replica.shardId());
    assertEquals(shardEntry.getAllocationId(), replica.allocationId().getId());
    if (randomBoolean()) {
        // simulate success
        transport.handleResponse(shardFailedRequest.requestId, TransportResponse.Empty.INSTANCE);
        assertTrue(success.get());
        assertNull(failure.get());
        assertNull(ignoredFailure.get());
    } else if (randomBoolean()) {
        // simulate the primary has been demoted
        transport.handleRemoteError(shardFailedRequest.requestId, new ShardStateAction.NoLongerPrimaryShardException(replica.shardId(), "shard-failed-test"));
        assertFalse(success.get());
        assertNotNull(failure.get());
        assertNull(ignoredFailure.get());
    } else {
        // simulated an "ignored" exception
        transport.handleRemoteError(shardFailedRequest.requestId, new NodeClosedException(state.nodes().getLocalNode()));
        assertFalse(success.get());
        assertNull(failure.get());
        assertNotNull(ignoredFailure.get());
    }
}
Also used : IndexShardRoutingTable(org.elasticsearch.cluster.routing.IndexShardRoutingTable) ShardStateAction(org.elasticsearch.cluster.action.shard.ShardStateAction) Matchers.anyString(org.mockito.Matchers.anyString) ElasticsearchException(org.elasticsearch.ElasticsearchException) ShardId(org.elasticsearch.index.shard.ShardId) NodeClosedException(org.elasticsearch.node.NodeClosedException) ReplicationOperation(org.elasticsearch.action.support.replication.ReplicationOperation) ClusterState(org.elasticsearch.cluster.ClusterState) CapturingTransport(org.elasticsearch.test.transport.CapturingTransport) AtomicReference(java.util.concurrent.atomic.AtomicReference) TransportException(org.elasticsearch.transport.TransportException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) TransportService(org.elasticsearch.transport.TransportService) 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 15 with PlainActionFuture

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

the class TransportInstanceSingleOperationActionTests method testFailureWithoutRetry.

public void testFailureWithoutRetry() throws Exception {
    Request request = new Request().index("test");
    request.shardId = new ShardId("test", "_na_", 0);
    PlainActionFuture<Response> listener = new PlainActionFuture<>();
    setState(clusterService, ClusterStateCreationUtils.state("test", randomBoolean(), ShardRoutingState.STARTED));
    action.new AsyncSingleAction(request, listener).start();
    assertThat(transport.capturedRequests().length, equalTo(1));
    long requestId = transport.capturedRequests()[0].requestId;
    transport.clear();
    // this should not trigger retry or anything and the listener should report exception immediately
    transport.handleRemoteError(requestId, new TransportException("a generic transport exception", new Exception("generic test exception")));
    try {
        // result should return immediately
        assertTrue(listener.isDone());
        listener.get();
        fail("this should fail with a transport exception");
    } catch (ExecutionException t) {
        if (ExceptionsHelper.unwrap(t, TransportException.class) == null) {
            logger.info("expected TransportException  but got ", t);
            fail("expected and TransportException");
        }
    }
}
Also used : ShardId(org.elasticsearch.index.shard.ShardId) ActionResponse(org.elasticsearch.action.ActionResponse) PlainActionFuture(org.elasticsearch.action.support.PlainActionFuture) IndicesRequest(org.elasticsearch.action.IndicesRequest) ExecutionException(java.util.concurrent.ExecutionException) ConnectTransportException(org.elasticsearch.transport.ConnectTransportException) TransportException(org.elasticsearch.transport.TransportException) TimeoutException(java.util.concurrent.TimeoutException) ConnectTransportException(org.elasticsearch.transport.ConnectTransportException) ClusterBlockException(org.elasticsearch.cluster.block.ClusterBlockException) ExecutionException(java.util.concurrent.ExecutionException) TransportException(org.elasticsearch.transport.TransportException)

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