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 + "]"));
}
}
}
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");
}
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));
}
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);
}
}
}
}
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());
}
Aggregations