Search in sources :

Example 96 with PlainActionFuture

use of org.opensearch.action.support.PlainActionFuture in project OpenSearch by opensearch-project.

the class TransportReplicationActionTests method testPrimaryActionRejectsWrongAidOrWrongTerm.

/**
 * test that a primary request is rejected if it arrives at a shard with a wrong allocation id or term
 */
public void testPrimaryActionRejectsWrongAidOrWrongTerm() throws Exception {
    final String index = "test";
    final ShardId shardId = new ShardId(index, "_na_", 0);
    setState(clusterService, state(index, true, ShardRoutingState.STARTED));
    final ShardRouting primary = clusterService.state().routingTable().shardRoutingTable(shardId).primaryShard();
    final long primaryTerm = clusterService.state().metadata().index(shardId.getIndexName()).primaryTerm(shardId.id());
    PlainActionFuture<TransportResponse> listener = new PlainActionFuture<>();
    final boolean wrongAllocationId = randomBoolean();
    final long requestTerm = wrongAllocationId && randomBoolean() ? primaryTerm : primaryTerm + randomIntBetween(1, 10);
    Request request = new Request(shardId).timeout("1ms");
    action.handlePrimaryRequest(new TransportReplicationAction.ConcreteShardRequest<>(request, wrongAllocationId ? "_not_a_valid_aid_" : primary.allocationId().getId(), requestTerm), createTransportChannel(listener), maybeTask());
    try {
        listener.get();
        fail("using a wrong aid didn't fail the operation");
    } catch (ExecutionException execException) {
        Throwable throwable = execException.getCause();
        logger.debug("got exception:", throwable);
        assertTrue(throwable.getClass() + " is not a retry exception", action.retryPrimaryException(throwable));
        if (wrongAllocationId) {
            assertThat(throwable.getMessage(), containsString("expected allocation id [_not_a_valid_aid_] but found [" + primary.allocationId().getId() + "]"));
        } else {
            assertThat(throwable.getMessage(), containsString("expected allocation id [" + primary.allocationId().getId() + "] with term [" + requestTerm + "] but found [" + primaryTerm + "]"));
        }
    }
}
Also used : CreateIndexRequest(org.opensearch.action.admin.indices.create.CreateIndexRequest) CloseIndexRequest(org.opensearch.action.admin.indices.close.CloseIndexRequest) TransportRequest(org.opensearch.transport.TransportRequest) Matchers.hasToString(org.hamcrest.Matchers.hasToString) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) Mockito.anyString(org.mockito.Mockito.anyString) TransportResponse(org.opensearch.transport.TransportResponse) ShardId(org.opensearch.index.shard.ShardId) PlainActionFuture(org.opensearch.action.support.PlainActionFuture) ShardRouting(org.opensearch.cluster.routing.ShardRouting) TestShardRouting(org.opensearch.cluster.routing.TestShardRouting) ExecutionException(java.util.concurrent.ExecutionException)

Example 97 with PlainActionFuture

use of org.opensearch.action.support.PlainActionFuture in project OpenSearch by opensearch-project.

the class TransportReplicationActionTests method testBlocksInPrimaryAction.

public void testBlocksInPrimaryAction() {
    final boolean globalBlock = randomBoolean();
    final TestAction actionWithBlocks = new TestAction(Settings.EMPTY, "internal:actionWithBlocks", transportService, clusterService, shardStateAction, threadPool) {

        @Override
        protected ClusterBlockLevel globalBlockLevel() {
            return globalBlock ? ClusterBlockLevel.WRITE : null;
        }

        @Override
        public ClusterBlockLevel indexBlockLevel() {
            return globalBlock == false ? ClusterBlockLevel.WRITE : null;
        }
    };
    final String index = "index";
    final ShardId shardId = new ShardId(index, "_na_", 0);
    setState(clusterService, stateWithActivePrimary(index, true, randomInt(5)));
    final ClusterBlocks.Builder block = ClusterBlocks.builder();
    if (globalBlock) {
        block.addGlobalBlock(new ClusterBlock(randomIntBetween(1, 16), "test global block", randomBoolean(), randomBoolean(), randomBoolean(), RestStatus.BAD_REQUEST, ClusterBlockLevel.ALL));
    } else {
        block.addIndexBlock(index, new ClusterBlock(randomIntBetween(1, 16), "test index block", randomBoolean(), randomBoolean(), randomBoolean(), RestStatus.FORBIDDEN, ClusterBlockLevel.READ_WRITE));
    }
    setState(clusterService, ClusterState.builder(clusterService.state()).blocks(block));
    final ClusterState clusterState = clusterService.state();
    final String targetAllocationID = clusterState.getRoutingTable().shardRoutingTable(shardId).primaryShard().allocationId().getId();
    final long primaryTerm = clusterState.metadata().index(index).primaryTerm(shardId.id());
    final Request request = new Request(shardId);
    final ReplicationTask task = maybeTask();
    final PlainActionFuture<TestResponse> listener = new PlainActionFuture<>();
    final TransportReplicationAction.ConcreteShardRequest<Request> primaryRequest = new TransportReplicationAction.ConcreteShardRequest<>(request, targetAllocationID, primaryTerm);
    final TransportReplicationAction.AsyncPrimaryAction asyncPrimaryActionWithBlocks = actionWithBlocks.new AsyncPrimaryAction(primaryRequest, listener, task);
    asyncPrimaryActionWithBlocks.run();
    final ExecutionException exception = expectThrows(ExecutionException.class, listener::get);
    assertThat(exception.getCause(), instanceOf(ClusterBlockException.class));
    assertThat(exception.getCause(), hasToString(containsString("test " + (globalBlock ? "global" : "index") + " block")));
    assertPhase(task, "finished");
}
Also used : ClusterState(org.opensearch.cluster.ClusterState) ClusterBlocks(org.opensearch.cluster.block.ClusterBlocks) CreateIndexRequest(org.opensearch.action.admin.indices.create.CreateIndexRequest) CloseIndexRequest(org.opensearch.action.admin.indices.close.CloseIndexRequest) TransportRequest(org.opensearch.transport.TransportRequest) Matchers.hasToString(org.hamcrest.Matchers.hasToString) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) Mockito.anyString(org.mockito.Mockito.anyString) ClusterBlockException(org.opensearch.cluster.block.ClusterBlockException) ShardId(org.opensearch.index.shard.ShardId) ClusterBlock(org.opensearch.cluster.block.ClusterBlock) PlainActionFuture(org.opensearch.action.support.PlainActionFuture) ExecutionException(java.util.concurrent.ExecutionException)

Example 98 with PlainActionFuture

use of org.opensearch.action.support.PlainActionFuture in project OpenSearch by opensearch-project.

the class TransportReplicationActionTests method testSeqNoIsSetOnPrimary.

public void testSeqNoIsSetOnPrimary() {
    final String index = "test";
    final ShardId shardId = new ShardId(index, "_na_", 0);
    // we use one replica to check the primary term was set on the operation and sent to the replica
    setState(clusterService, state(index, true, ShardRoutingState.STARTED, randomFrom(ShardRoutingState.INITIALIZING, ShardRoutingState.STARTED)));
    logger.debug("--> using initial state:\n{}", clusterService.state());
    final ShardRouting routingEntry = clusterService.state().getRoutingTable().index("test").shard(0).primaryShard();
    final long primaryTerm = clusterService.state().metadata().index(index).primaryTerm(shardId.id());
    Request request = new Request(shardId);
    TransportReplicationAction.ConcreteShardRequest<Request> concreteShardRequest = new TransportReplicationAction.ConcreteShardRequest<>(request, routingEntry.allocationId().getId(), primaryTerm);
    PlainActionFuture<TransportResponse> listener = new PlainActionFuture<>();
    final IndexShard shard = mockIndexShard(shardId, clusterService);
    when(shard.getPendingPrimaryTerm()).thenReturn(primaryTerm);
    when(shard.routingEntry()).thenReturn(routingEntry);
    when(shard.isRelocatedPrimary()).thenReturn(false);
    IndexShardRoutingTable shardRoutingTable = clusterService.state().routingTable().shardRoutingTable(shardId);
    Set<String> inSyncIds = randomBoolean() ? singleton(routingEntry.allocationId().getId()) : clusterService.state().metadata().index(index).inSyncAllocationIds(0);
    ReplicationGroup replicationGroup = new ReplicationGroup(shardRoutingTable, inSyncIds, shardRoutingTable.getAllAllocationIds(), 0);
    when(shard.getReplicationGroup()).thenReturn(replicationGroup);
    PendingReplicationActions replicationActions = new PendingReplicationActions(shardId, threadPool);
    replicationActions.accept(replicationGroup);
    when(shard.getPendingReplicationActions()).thenReturn(replicationActions);
    doAnswer(invocation -> {
        count.incrementAndGet();
        // noinspection unchecked
        ((ActionListener<Releasable>) invocation.getArguments()[0]).onResponse(count::decrementAndGet);
        return null;
    }).when(shard).acquirePrimaryOperationPermit(any(), anyString(), any(), eq(forceExecute));
    when(shard.getActiveOperationsCount()).thenAnswer(i -> count.get());
    final IndexService indexService = mock(IndexService.class);
    when(indexService.getShard(shard.shardId().id())).thenReturn(shard);
    final IndicesService indicesService = mock(IndicesService.class);
    when(indicesService.indexServiceSafe(shard.shardId().getIndex())).thenReturn(indexService);
    TestAction action = new TestAction(Settings.EMPTY, "internal:testSeqNoIsSetOnPrimary", transportService, clusterService, shardStateAction, threadPool, indicesService);
    action.handlePrimaryRequest(concreteShardRequest, createTransportChannel(listener), null);
    CapturingTransport.CapturedRequest[] requestsToReplicas = transport.capturedRequests();
    assertThat(requestsToReplicas, arrayWithSize(1));
    // noinspection unchecked
    assertThat(((TransportReplicationAction.ConcreteShardRequest<Request>) requestsToReplicas[0].request).getPrimaryTerm(), equalTo(primaryTerm));
}
Also used : IndexShardRoutingTable(org.opensearch.cluster.routing.IndexShardRoutingTable) IndexService(org.opensearch.index.IndexService) IndexShard(org.opensearch.index.shard.IndexShard) CreateIndexRequest(org.opensearch.action.admin.indices.create.CreateIndexRequest) CloseIndexRequest(org.opensearch.action.admin.indices.close.CloseIndexRequest) TransportRequest(org.opensearch.transport.TransportRequest) IndicesService(org.opensearch.indices.IndicesService) Matchers.hasToString(org.hamcrest.Matchers.hasToString) CoreMatchers.containsString(org.hamcrest.CoreMatchers.containsString) Mockito.anyString(org.mockito.Mockito.anyString) ReplicationGroup(org.opensearch.index.shard.ReplicationGroup) TransportResponse(org.opensearch.transport.TransportResponse) ShardId(org.opensearch.index.shard.ShardId) ActionListener(org.opensearch.action.ActionListener) PlainActionFuture(org.opensearch.action.support.PlainActionFuture) ShardRouting(org.opensearch.cluster.routing.ShardRouting) TestShardRouting(org.opensearch.cluster.routing.TestShardRouting)

Example 99 with PlainActionFuture

use of org.opensearch.action.support.PlainActionFuture in project OpenSearch by opensearch-project.

the class TransportReplicationAllPermitsAcquisitionTests method testTransportReplicationActionWithAllPermits.

public void testTransportReplicationActionWithAllPermits() throws Exception {
    final int numOperations = scaledRandomIntBetween(4, 32);
    final int delayedOperations = randomIntBetween(1, numOperations);
    logger.trace("starting [{}] operations, among which the first [{}] started ops should be blocked by [{}]", numOperations, delayedOperations, block);
    final CyclicBarrier delayedOperationsBarrier = new CyclicBarrier(delayedOperations + 1);
    final List<Thread> threads = new ArrayList<>(delayedOperationsBarrier.getParties());
    @SuppressWarnings("unchecked") final PlainActionFuture<Response>[] futures = new PlainActionFuture[numOperations];
    final TestAction[] actions = new TestAction[numOperations];
    for (int i = 0; i < numOperations; i++) {
        final int threadId = i;
        final boolean delayed = (threadId < delayedOperations);
        final PlainActionFuture<Response> listener = new PlainActionFuture<>();
        futures[threadId] = listener;
        final TestAction singlePermitAction = new SinglePermitWithBlocksAction(Settings.EMPTY, "cluster:admin/test/single_permit[" + threadId + "]", transportService, clusterService, shardStateAction, threadPool, shardId, primary, replica, globalBlock);
        actions[threadId] = singlePermitAction;
        Thread thread = new Thread(() -> {
            final TransportReplicationAction.ConcreteShardRequest<Request> primaryRequest = new TransportReplicationAction.ConcreteShardRequest<>(request(), allocationId(), primaryTerm());
            TransportReplicationAction.AsyncPrimaryAction asyncPrimaryAction = singlePermitAction.new AsyncPrimaryAction(primaryRequest, listener, null) {

                @Override
                protected void doRun() throws Exception {
                    if (delayed) {
                        logger.trace("op [{}] has started and will resume execution once allPermitsAction is terminated", threadId);
                        delayedOperationsBarrier.await();
                    }
                    super.doRun();
                }

                @Override
                void runWithPrimaryShardReference(final TransportReplicationAction.PrimaryShardReference reference) {
                    assertThat(reference.indexShard.getActiveOperationsCount(), greaterThan(0));
                    assertSame(primary, reference.indexShard);
                    assertBlockIsPresentForDelayedOp();
                    super.runWithPrimaryShardReference(reference);
                }

                @Override
                public void onFailure(Exception e) {
                    assertBlockIsPresentForDelayedOp();
                    super.onFailure(e);
                }

                private void assertBlockIsPresentForDelayedOp() {
                    if (delayed) {
                        final ClusterState clusterState = clusterService.state();
                        if (globalBlock) {
                            assertTrue("Global block must exist", clusterState.blocks().hasGlobalBlock(block));
                        } else {
                            String indexName = primary.shardId().getIndexName();
                            assertTrue("Index block must exist", clusterState.blocks().hasIndexBlock(indexName, block));
                        }
                    }
                }
            };
            asyncPrimaryAction.run();
        });
        threads.add(thread);
        thread.start();
    }
    logger.trace("now starting the operation that acquires all permits and sets the block in the cluster state");
    // An action which acquires all operation permits during execution and set a block
    final TestAction allPermitsAction = new AllPermitsThenBlockAction(Settings.EMPTY, "cluster:admin/test/all_permits", transportService, clusterService, shardStateAction, threadPool, shardId, primary, replica);
    final PlainActionFuture<Response> allPermitFuture = new PlainActionFuture<>();
    Thread thread = new Thread(() -> {
        final TransportReplicationAction.ConcreteShardRequest<Request> primaryRequest = new TransportReplicationAction.ConcreteShardRequest<>(request(), allocationId(), primaryTerm());
        TransportReplicationAction.AsyncPrimaryAction asyncPrimaryAction = allPermitsAction.new AsyncPrimaryAction(primaryRequest, allPermitFuture, null) {

            @Override
            void runWithPrimaryShardReference(final TransportReplicationAction.PrimaryShardReference reference) {
                assertEquals("All permits must be acquired", IndexShard.OPERATIONS_BLOCKED, reference.indexShard.getActiveOperationsCount());
                assertSame(primary, reference.indexShard);
                final ClusterState clusterState = clusterService.state();
                final ClusterBlocks.Builder blocks = ClusterBlocks.builder();
                if (globalBlock) {
                    assertFalse("Global block must not exist yet", clusterState.blocks().hasGlobalBlock(block));
                    blocks.addGlobalBlock(block);
                } else {
                    String indexName = reference.indexShard.shardId().getIndexName();
                    assertFalse("Index block must not exist yet", clusterState.blocks().hasIndexBlock(indexName, block));
                    blocks.addIndexBlock(indexName, block);
                }
                logger.trace("adding test block to cluster state {}", block);
                setState(clusterService, ClusterState.builder(clusterState).blocks(blocks));
                try {
                    logger.trace("releasing delayed operations");
                    delayedOperationsBarrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    onFailure(e);
                }
                super.runWithPrimaryShardReference(reference);
            }
        };
        asyncPrimaryAction.run();
    });
    threads.add(thread);
    thread.start();
    logger.trace("waiting for all operations to terminate");
    for (Thread t : threads) {
        t.join();
    }
    final Response allPermitsResponse = allPermitFuture.get();
    assertSuccessfulOperation(allPermitsAction, allPermitsResponse);
    for (int i = 0; i < numOperations; i++) {
        final PlainActionFuture<Response> future = futures[i];
        final TestAction action = actions[i];
        if (i < delayedOperations) {
            ExecutionException exception = expectThrows(ExecutionException.class, "delayed operation should have failed", future::get);
            assertFailedOperation(action, exception);
        } else {
            // non delayed operation might fail depending on the order they were executed
            try {
                assertSuccessfulOperation(action, futures[i].get());
            } catch (final ExecutionException e) {
                assertFailedOperation(action, e);
            }
        }
    }
}
Also used : BrokenBarrierException(java.util.concurrent.BrokenBarrierException) ArrayList(java.util.ArrayList) ExecutionException(java.util.concurrent.ExecutionException) ClusterState(org.opensearch.cluster.ClusterState) ClusterBlocks(org.opensearch.cluster.block.ClusterBlocks) TransportRequest(org.opensearch.transport.TransportRequest) ClusterBlockException(org.opensearch.cluster.block.ClusterBlockException) TransportException(org.opensearch.transport.TransportException) IOException(java.io.IOException) BrokenBarrierException(java.util.concurrent.BrokenBarrierException) ExecutionException(java.util.concurrent.ExecutionException) CyclicBarrier(java.util.concurrent.CyclicBarrier) PlainActionFuture(org.opensearch.action.support.PlainActionFuture)

Example 100 with PlainActionFuture

use of org.opensearch.action.support.PlainActionFuture in project OpenSearch by opensearch-project.

the class TransportWriteActionForIndexingPressureTests method testIndexingPressureOperationStartedForPrimaryShard.

public void testIndexingPressureOperationStartedForPrimaryShard() {
    final ShardId shardId = new ShardId("test", "_na_", 0);
    final ClusterState state = state(shardId.getIndexName(), true, ShardRoutingState.STARTED, ShardRoutingState.STARTED);
    setState(clusterService, state);
    final ShardRouting replicaRouting = state.getRoutingTable().shardRoutingTable(shardId).replicaShards().get(0);
    final ReplicationTask task = maybeTask();
    final Settings settings = Settings.builder().put(ShardIndexingPressureSettings.SHARD_INDEXING_PRESSURE_ENABLED.getKey(), true).build();
    this.indexingPressureService = new IndexingPressureService(settings, clusterService);
    TestAction action = new TestAction(settings, "internal:testActionWithExceptions", transportService, clusterService, shardStateAction, threadPool);
    action.handlePrimaryRequest(new TransportReplicationAction.ConcreteReplicaRequest<>(new TestRequest(), replicaRouting.allocationId().getId(), randomNonNegativeLong(), randomNonNegativeLong(), randomNonNegativeLong()), createTransportChannel(new PlainActionFuture<>()), task);
    CommonStatsFlags statsFlag = new CommonStatsFlags();
    statsFlag.includeAllShardIndexingPressureTrackers(true);
    IndexingPressurePerShardStats shardStats = this.indexingPressureService.shardStats(statsFlag).getIndexingPressureShardStats(shardId);
    assertPhase(task, "finished");
    assertTrue(!Objects.isNull(shardStats));
    assertEquals(100, shardStats.getTotalPrimaryBytes());
}
Also used : ClusterState(org.opensearch.cluster.ClusterState) IndexingPressureService(org.opensearch.index.IndexingPressureService) CommonStatsFlags(org.opensearch.action.admin.indices.stats.CommonStatsFlags) ShardId(org.opensearch.index.shard.ShardId) PlainActionFuture(org.opensearch.action.support.PlainActionFuture) ShardRouting(org.opensearch.cluster.routing.ShardRouting) ShardIndexingPressureSettings(org.opensearch.index.ShardIndexingPressureSettings) Settings(org.opensearch.common.settings.Settings) ClusterSettings(org.opensearch.common.settings.ClusterSettings) IndexingPressurePerShardStats(org.opensearch.index.stats.IndexingPressurePerShardStats)

Aggregations

PlainActionFuture (org.opensearch.action.support.PlainActionFuture)191 ActionListener (org.opensearch.action.ActionListener)59 ShardId (org.opensearch.index.shard.ShardId)55 Settings (org.opensearch.common.settings.Settings)46 IOException (java.io.IOException)43 ActionFilters (org.opensearch.action.support.ActionFilters)43 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)42 DiscoveryNode (org.opensearch.cluster.node.DiscoveryNode)42 CountDownLatch (java.util.concurrent.CountDownLatch)41 ClusterState (org.opensearch.cluster.ClusterState)40 ShardRouting (org.opensearch.cluster.routing.ShardRouting)39 ExecutionException (java.util.concurrent.ExecutionException)38 List (java.util.List)37 ThreadPool (org.opensearch.threadpool.ThreadPool)37 ArrayList (java.util.ArrayList)35 Matchers.containsString (org.hamcrest.Matchers.containsString)31 HashSet (java.util.HashSet)30 IndexShard (org.opensearch.index.shard.IndexShard)29 Mockito.anyString (org.mockito.Mockito.anyString)28 TransportRequest (org.opensearch.transport.TransportRequest)28