use of org.opensearch.common.lease.Releasable in project OpenSearch by opensearch-project.
the class IndexShardTests method testPrimaryPromotionDelaysOperations.
public void testPrimaryPromotionDelaysOperations() throws IOException, BrokenBarrierException, InterruptedException {
final IndexShard indexShard = newShard(false);
recoveryEmptyReplica(indexShard, randomBoolean());
final int operations = scaledRandomIntBetween(1, 64);
final CyclicBarrier barrier = new CyclicBarrier(1 + operations);
final CountDownLatch latch = new CountDownLatch(operations);
final CountDownLatch operationLatch = new CountDownLatch(1);
final List<Thread> threads = new ArrayList<>();
for (int i = 0; i < operations; i++) {
final String id = "t_" + i;
final Thread thread = new Thread(() -> {
try {
barrier.await();
} catch (final BrokenBarrierException | InterruptedException e) {
throw new RuntimeException(e);
}
indexShard.acquireReplicaOperationPermit(indexShard.getPendingPrimaryTerm(), indexShard.getLastKnownGlobalCheckpoint(), indexShard.getMaxSeqNoOfUpdatesOrDeletes(), new ActionListener<Releasable>() {
@Override
public void onResponse(Releasable releasable) {
latch.countDown();
try {
operationLatch.await();
} catch (final InterruptedException e) {
throw new RuntimeException(e);
}
releasable.close();
}
@Override
public void onFailure(Exception e) {
throw new RuntimeException(e);
}
}, ThreadPool.Names.WRITE, id);
});
thread.start();
threads.add(thread);
}
barrier.await();
latch.await();
final ShardRouting replicaRouting = indexShard.routingEntry();
promoteReplica(indexShard, Collections.singleton(replicaRouting.allocationId().getId()), new IndexShardRoutingTable.Builder(replicaRouting.shardId()).addShard(replicaRouting).build());
final int delayedOperations = scaledRandomIntBetween(1, 64);
final CyclicBarrier delayedOperationsBarrier = new CyclicBarrier(1 + delayedOperations);
final CountDownLatch delayedOperationsLatch = new CountDownLatch(delayedOperations);
final AtomicLong counter = new AtomicLong();
final List<Thread> delayedThreads = new ArrayList<>();
for (int i = 0; i < delayedOperations; i++) {
final String id = "d_" + i;
final Thread thread = new Thread(() -> {
try {
delayedOperationsBarrier.await();
} catch (final BrokenBarrierException | InterruptedException e) {
throw new RuntimeException(e);
}
indexShard.acquirePrimaryOperationPermit(new ActionListener<Releasable>() {
@Override
public void onResponse(Releasable releasable) {
counter.incrementAndGet();
releasable.close();
delayedOperationsLatch.countDown();
}
@Override
public void onFailure(Exception e) {
throw new RuntimeException(e);
}
}, ThreadPool.Names.WRITE, id);
});
thread.start();
delayedThreads.add(thread);
}
delayedOperationsBarrier.await();
assertThat(counter.get(), equalTo(0L));
operationLatch.countDown();
for (final Thread thread : threads) {
thread.join();
}
delayedOperationsLatch.await();
assertThat(counter.get(), equalTo((long) delayedOperations));
for (final Thread thread : delayedThreads) {
thread.join();
}
closeShards(indexShard);
}
use of org.opensearch.common.lease.Releasable in project OpenSearch by opensearch-project.
the class IndexShardTests method testRestoreLocalHistoryFromTranslogOnPromotion.
public void testRestoreLocalHistoryFromTranslogOnPromotion() throws IOException, InterruptedException {
final IndexShard indexShard = newStartedShard(false);
final int operations = 1024 - scaledRandomIntBetween(0, 1024);
indexOnReplicaWithGaps(indexShard, operations, Math.toIntExact(SequenceNumbers.NO_OPS_PERFORMED));
final long maxSeqNo = indexShard.seqNoStats().getMaxSeqNo();
final long globalCheckpointOnReplica = randomLongBetween(UNASSIGNED_SEQ_NO, indexShard.getLocalCheckpoint());
indexShard.updateGlobalCheckpointOnReplica(globalCheckpointOnReplica, "test");
final long globalCheckpoint = randomLongBetween(UNASSIGNED_SEQ_NO, indexShard.getLocalCheckpoint());
final long maxSeqNoOfUpdatesOrDeletesBeforeRollback = indexShard.getMaxSeqNoOfUpdatesOrDeletes();
final Set<String> docsBeforeRollback = getShardDocUIDs(indexShard);
final CountDownLatch latch = new CountDownLatch(1);
randomReplicaOperationPermitAcquisition(indexShard, indexShard.getPendingPrimaryTerm() + 1, globalCheckpoint, randomLongBetween(SequenceNumbers.NO_OPS_PERFORMED, maxSeqNo), new ActionListener<Releasable>() {
@Override
public void onResponse(Releasable releasable) {
releasable.close();
latch.countDown();
}
@Override
public void onFailure(Exception e) {
}
}, "");
latch.await();
if (globalCheckpoint < maxSeqNo) {
assertThat(indexShard.getMaxSeqNoOfUpdatesOrDeletes(), equalTo(maxSeqNo));
} else {
assertThat(indexShard.getMaxSeqNoOfUpdatesOrDeletes(), equalTo(maxSeqNoOfUpdatesOrDeletesBeforeRollback));
}
final ShardRouting newRouting = indexShard.routingEntry().moveActiveReplicaToPrimary();
final CountDownLatch resyncLatch = new CountDownLatch(1);
indexShard.updateShardState(newRouting, indexShard.getPendingPrimaryTerm() + 1, (s, r) -> resyncLatch.countDown(), 1L, Collections.singleton(newRouting.allocationId().getId()), new IndexShardRoutingTable.Builder(newRouting.shardId()).addShard(newRouting).build());
resyncLatch.await();
assertThat(indexShard.getLocalCheckpoint(), equalTo(maxSeqNo));
assertThat(indexShard.seqNoStats().getMaxSeqNo(), equalTo(maxSeqNo));
assertThat(getShardDocUIDs(indexShard), equalTo(docsBeforeRollback));
if (globalCheckpoint < maxSeqNo) {
assertThat(indexShard.getMaxSeqNoOfUpdatesOrDeletes(), equalTo(maxSeqNo));
} else {
assertThat(indexShard.getMaxSeqNoOfUpdatesOrDeletes(), equalTo(maxSeqNoOfUpdatesOrDeletesBeforeRollback));
}
closeShard(indexShard, false);
}
use of org.opensearch.common.lease.Releasable in project OpenSearch by opensearch-project.
the class IndexShardTests method testDelayedOperationsBeforeAndAfterRelocated.
public void testDelayedOperationsBeforeAndAfterRelocated() throws Exception {
final IndexShard shard = newStartedShard(true);
final ShardRouting routing = ShardRoutingHelper.relocate(shard.routingEntry(), "other_node");
IndexShardTestCase.updateRoutingEntry(shard, routing);
final CountDownLatch startRecovery = new CountDownLatch(1);
final CountDownLatch relocationStarted = new CountDownLatch(1);
Thread recoveryThread = new Thread(() -> {
try {
startRecovery.await();
shard.relocated(routing.getTargetRelocatingShard().allocationId().getId(), primaryContext -> relocationStarted.countDown());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
recoveryThread.start();
final int numberOfAcquisitions = randomIntBetween(1, 10);
final List<Runnable> assertions = new ArrayList<>(numberOfAcquisitions);
final int recoveryIndex = randomIntBetween(0, numberOfAcquisitions - 1);
for (int i = 0; i < numberOfAcquisitions; i++) {
final PlainActionFuture<Releasable> onLockAcquired;
if (i < recoveryIndex) {
final AtomicBoolean invoked = new AtomicBoolean();
onLockAcquired = new PlainActionFuture<Releasable>() {
@Override
public void onResponse(Releasable releasable) {
invoked.set(true);
releasable.close();
super.onResponse(releasable);
}
@Override
public void onFailure(Exception e) {
throw new AssertionError();
}
};
assertions.add(() -> assertTrue(invoked.get()));
} else if (recoveryIndex == i) {
startRecovery.countDown();
relocationStarted.await();
onLockAcquired = new PlainActionFuture<>();
assertions.add(() -> {
final ExecutionException e = expectThrows(ExecutionException.class, () -> onLockAcquired.get(30, TimeUnit.SECONDS));
assertThat(e.getCause(), instanceOf(ShardNotInPrimaryModeException.class));
assertThat(e.getCause(), hasToString(containsString("shard is not in primary mode")));
});
} else {
onLockAcquired = new PlainActionFuture<>();
assertions.add(() -> {
final ExecutionException e = expectThrows(ExecutionException.class, () -> onLockAcquired.get(30, TimeUnit.SECONDS));
assertThat(e.getCause(), instanceOf(ShardNotInPrimaryModeException.class));
assertThat(e.getCause(), hasToString(containsString("shard is not in primary mode")));
});
}
shard.acquirePrimaryOperationPermit(onLockAcquired, ThreadPool.Names.WRITE, "i_" + i);
}
for (final Runnable assertion : assertions) {
assertion.run();
}
recoveryThread.join();
closeShards(shard);
}
use of org.opensearch.common.lease.Releasable in project OpenSearch by opensearch-project.
the class TranslogDeletionPolicyTests method testRetentionHierarchy.
/**
* Tests that age trumps size but recovery trumps both.
*/
public void testRetentionHierarchy() throws IOException {
long now = System.currentTimeMillis();
Tuple<List<TranslogReader>, TranslogWriter> readersAndWriter = createReadersAndWriter(now);
List<BaseTranslogReader> allGens = new ArrayList<>(readersAndWriter.v1());
allGens.add(readersAndWriter.v2());
try {
DefaultTranslogDeletionPolicy deletionPolicy = new MockDeletionPolicy(now, Long.MAX_VALUE, Long.MAX_VALUE, Integer.MAX_VALUE);
int selectedReader = randomIntBetween(0, allGens.size() - 1);
final long selectedGenerationByAge = allGens.get(selectedReader).generation;
long maxAge = now - allGens.get(selectedReader).getLastModifiedTime();
selectedReader = randomIntBetween(0, allGens.size() - 1);
final long selectedGenerationBySize = allGens.get(selectedReader).generation;
long size = allGens.stream().skip(selectedReader).map(BaseTranslogReader::sizeInBytes).reduce(Long::sum).get();
selectedReader = randomIntBetween(0, allGens.size() - 1);
final long selectedGenerationByTotalFiles = allGens.get(selectedReader).generation;
deletionPolicy.setRetentionAgeInMillis(maxAge);
deletionPolicy.setRetentionSizeInBytes(size);
final int totalFiles = allGens.size() - selectedReader;
deletionPolicy.setRetentionTotalFiles(totalFiles);
assertMinGenRequired(deletionPolicy, readersAndWriter, max3(selectedGenerationByAge, selectedGenerationBySize, selectedGenerationByTotalFiles));
// make a new policy as committed gen can't go backwards (for now)
deletionPolicy = new MockDeletionPolicy(now, size, maxAge, totalFiles);
assertMinGenRequired(deletionPolicy, readersAndWriter, max3(selectedGenerationByAge, selectedGenerationBySize, selectedGenerationByTotalFiles));
long viewGen = randomFrom(allGens).generation;
try (Releasable ignored = deletionPolicy.acquireTranslogGen(viewGen)) {
assertMinGenRequired(deletionPolicy, readersAndWriter, min(viewGen, max3(selectedGenerationByAge, selectedGenerationBySize, selectedGenerationByTotalFiles)));
// disable age
deletionPolicy.setRetentionAgeInMillis(-1);
assertMinGenRequired(deletionPolicy, readersAndWriter, min(viewGen, Math.max(selectedGenerationBySize, selectedGenerationByTotalFiles)));
// disable size
deletionPolicy.setRetentionAgeInMillis(maxAge);
deletionPolicy.setRetentionSizeInBytes(-1);
assertMinGenRequired(deletionPolicy, readersAndWriter, min(viewGen, Math.max(selectedGenerationByAge, selectedGenerationByTotalFiles)));
// disable age and zie
deletionPolicy.setRetentionAgeInMillis(-1);
deletionPolicy.setRetentionSizeInBytes(-1);
assertMinGenRequired(deletionPolicy, readersAndWriter, viewGen);
// disable total files
deletionPolicy.setRetentionTotalFiles(0);
assertMinGenRequired(deletionPolicy, readersAndWriter, viewGen);
}
} finally {
IOUtils.close(readersAndWriter.v1());
IOUtils.close(readersAndWriter.v2());
}
}
use of org.opensearch.common.lease.Releasable in project OpenSearch by opensearch-project.
the class TransportWriteActionTests method mockIndexShard.
private IndexShard mockIndexShard(ShardId shardId, ClusterService clusterService) {
final IndexShard indexShard = mock(IndexShard.class);
doAnswer(invocation -> {
ActionListener<Releasable> callback = (ActionListener<Releasable>) invocation.getArguments()[0];
count.incrementAndGet();
callback.onResponse(count::decrementAndGet);
return null;
}).when(indexShard).acquirePrimaryOperationPermit(any(ActionListener.class), anyString(), any());
doAnswer(invocation -> {
long term = (Long) invocation.getArguments()[0];
ActionListener<Releasable> callback = (ActionListener<Releasable>) invocation.getArguments()[1];
final long primaryTerm = indexShard.getPendingPrimaryTerm();
if (term < primaryTerm) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "%s operation term [%d] is too old (current [%d])", shardId, term, primaryTerm));
}
count.incrementAndGet();
callback.onResponse(count::decrementAndGet);
return null;
}).when(indexShard).acquireReplicaOperationPermit(anyLong(), anyLong(), anyLong(), any(ActionListener.class), anyString(), any());
when(indexShard.routingEntry()).thenAnswer(invocationOnMock -> {
final ClusterState state = clusterService.state();
final RoutingNode node = state.getRoutingNodes().node(state.nodes().getLocalNodeId());
final ShardRouting routing = node.getByShardId(shardId);
if (routing == null) {
throw new ShardNotFoundException(shardId, "shard is no longer assigned to current node");
}
return routing;
});
when(indexShard.isRelocatedPrimary()).thenAnswer(invocationOnMock -> isRelocated.get());
doThrow(new AssertionError("failed shard is not supported")).when(indexShard).failShard(anyString(), any(Exception.class));
when(indexShard.getPendingPrimaryTerm()).thenAnswer(i -> clusterService.state().metadata().getIndexSafe(shardId.getIndex()).primaryTerm(shardId.id()));
return indexShard;
}
Aggregations