use of org.opensearch.common.lease.Releasable in project OpenSearch by opensearch-project.
the class IndexShardOperationPermitsTests method testAsyncBlockOperationsRace.
public void testAsyncBlockOperationsRace() throws Exception {
// we racily submit operations and a delay, and then ensure that all operations were actually completed
final int operations = scaledRandomIntBetween(1, 64);
final CyclicBarrier barrier = new CyclicBarrier(1 + 1 + operations);
final CountDownLatch operationLatch = new CountDownLatch(1 + operations);
final Set<Integer> values = Collections.newSetFromMap(new ConcurrentHashMap<>());
final List<Thread> threads = new ArrayList<>();
for (int i = 0; i < operations; i++) {
final int value = i;
final Thread thread = new Thread(() -> {
try {
barrier.await();
} catch (final BrokenBarrierException | InterruptedException e) {
throw new RuntimeException(e);
}
permits.acquire(new ActionListener<Releasable>() {
@Override
public void onResponse(Releasable releasable) {
values.add(value);
releasable.close();
operationLatch.countDown();
}
@Override
public void onFailure(Exception e) {
}
}, ThreadPool.Names.GENERIC, false, "");
});
thread.start();
threads.add(thread);
}
final Thread blockingThread = new Thread(() -> {
try {
barrier.await();
} catch (final BrokenBarrierException | InterruptedException e) {
throw new RuntimeException(e);
}
permits.asyncBlockOperations(wrap(() -> {
values.add(operations);
operationLatch.countDown();
}), 30, TimeUnit.MINUTES);
});
blockingThread.start();
barrier.await();
operationLatch.await();
for (final Thread thread : threads) {
thread.join();
}
blockingThread.join();
// check that all operations completed
for (int i = 0; i < operations; i++) {
assertTrue(values.contains(i));
}
assertTrue(values.contains(operations));
/*
* The block operation is executed on another thread and the operations can have completed before this thread has returned all the
* permits to the semaphore. We wait here until all generic threads are idle as an indication that all permits have been returned to
* the semaphore.
*/
assertBusy(() -> {
for (final ThreadPoolStats.Stats stats : threadPool.stats()) {
if (ThreadPool.Names.GENERIC.equals(stats.getName())) {
assertThat("Expected no active threads in GENERIC pool", stats.getActive(), equalTo(0));
return;
}
}
fail("Failed to find stats for the GENERIC thread pool");
});
}
use of org.opensearch.common.lease.Releasable in project OpenSearch by opensearch-project.
the class RetentionLeaseActionsTests method runActionUnderBlockTest.
/*
* Tests that use this method are ensuring that the asynchronous usage of the permits API when permit acquisition is blocked is
* correctly handler. In these scenarios, we first acquire all permits. Then we submit a request to one of the retention lease actions
* (via the consumer callback). That invocation will go asynchronous and be queued, since all permits are blocked. Then we release the
* permit block and except that the callbacks occur correctly. These assertions happen after returning from this method.
*/
private void runActionUnderBlockTest(final IndexService indexService, final BiConsumer<ShardId, CountDownLatch> consumer) throws InterruptedException {
final CountDownLatch blockedLatch = new CountDownLatch(1);
final CountDownLatch unblockLatch = new CountDownLatch(1);
indexService.getShard(0).acquireAllPrimaryOperationsPermits(new ActionListener<Releasable>() {
@Override
public void onResponse(final Releasable releasable) {
try (Releasable ignore = releasable) {
blockedLatch.countDown();
unblockLatch.await();
} catch (final InterruptedException e) {
onFailure(e);
}
}
@Override
public void onFailure(final Exception e) {
fail(e.toString());
}
}, TimeValue.timeValueHours(1));
blockedLatch.await();
final CountDownLatch actionLatch = new CountDownLatch(1);
consumer.accept(indexService.getShard(0).shardId(), actionLatch);
unblockLatch.countDown();
actionLatch.await();
}
use of org.opensearch.common.lease.Releasable in project OpenSearch by opensearch-project.
the class RefreshListenersTests method testDisallowAddListeners.
public void testDisallowAddListeners() throws Exception {
assertEquals(0, listeners.pendingCount());
DummyRefreshListener listener = new DummyRefreshListener();
assertFalse(listeners.addOrNotify(index("1").getTranslogLocation(), listener));
engine.refresh("I said so");
assertFalse(listener.forcedRefresh.get());
listener.assertNoError();
try (Releasable releaseable1 = listeners.forceRefreshes()) {
listener = new DummyRefreshListener();
assertTrue(listeners.addOrNotify(index("1").getTranslogLocation(), listener));
assertTrue(listener.forcedRefresh.get());
listener.assertNoError();
assertEquals(0, listeners.pendingCount());
try (Releasable releaseable2 = listeners.forceRefreshes()) {
listener = new DummyRefreshListener();
assertTrue(listeners.addOrNotify(index("1").getTranslogLocation(), listener));
assertTrue(listener.forcedRefresh.get());
listener.assertNoError();
assertEquals(0, listeners.pendingCount());
}
listener = new DummyRefreshListener();
assertTrue(listeners.addOrNotify(index("1").getTranslogLocation(), listener));
assertTrue(listener.forcedRefresh.get());
listener.assertNoError();
assertEquals(0, listeners.pendingCount());
}
assertFalse(listeners.addOrNotify(index("1").getTranslogLocation(), new DummyRefreshListener()));
assertEquals(1, listeners.pendingCount());
}
use of org.opensearch.common.lease.Releasable in project OpenSearch by opensearch-project.
the class IndexShardTests method testPrimaryPromotionRollsGeneration.
public void testPrimaryPromotionRollsGeneration() throws Exception {
final IndexShard indexShard = newStartedShard(false);
final long currentTranslogGeneration = getTranslog(indexShard).getGeneration().translogFileGeneration;
// promote the replica
final ShardRouting replicaRouting = indexShard.routingEntry();
final long newPrimaryTerm = indexShard.getPendingPrimaryTerm() + between(1, 10000);
final ShardRouting primaryRouting = newShardRouting(replicaRouting.shardId(), replicaRouting.currentNodeId(), null, true, ShardRoutingState.STARTED, replicaRouting.allocationId());
indexShard.updateShardState(primaryRouting, newPrimaryTerm, (shard, listener) -> {
}, 0L, Collections.singleton(primaryRouting.allocationId().getId()), new IndexShardRoutingTable.Builder(primaryRouting.shardId()).addShard(primaryRouting).build());
/*
* This operation completing means that the delay operation executed as part of increasing the primary term has completed and the
* translog generation has rolled.
*/
final CountDownLatch latch = new CountDownLatch(1);
indexShard.acquirePrimaryOperationPermit(new ActionListener<Releasable>() {
@Override
public void onResponse(Releasable releasable) {
releasable.close();
latch.countDown();
}
@Override
public void onFailure(Exception e) {
throw new RuntimeException(e);
}
}, ThreadPool.Names.GENERIC, "");
latch.await();
assertThat(getTranslog(indexShard).getGeneration().translogFileGeneration, equalTo(currentTranslogGeneration + 1));
assertThat(TestTranslog.getCurrentTerm(getTranslog(indexShard)), equalTo(newPrimaryTerm));
closeShards(indexShard);
}
use of org.opensearch.common.lease.Releasable in project OpenSearch by opensearch-project.
the class IndexShardTests method testLockingBeforeAndAfterRelocated.
public void testLockingBeforeAndAfterRelocated() throws Exception {
final IndexShard shard = newStartedShard(true);
final ShardRouting routing = ShardRoutingHelper.relocate(shard.routingEntry(), "other_node");
IndexShardTestCase.updateRoutingEntry(shard, routing);
CountDownLatch latch = new CountDownLatch(1);
Thread recoveryThread = new Thread(() -> {
latch.countDown();
try {
shard.relocated(routing.getTargetRelocatingShard().allocationId().getId(), primaryContext -> {
});
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
try (Releasable ignored = acquirePrimaryOperationPermitBlockingly(shard)) {
// start finalization of recovery
recoveryThread.start();
latch.await();
// recovery can only be finalized after we release the current primaryOperationLock
assertFalse(shard.isRelocatedPrimary());
}
// recovery can be now finalized
recoveryThread.join();
assertTrue(shard.isRelocatedPrimary());
final ExecutionException e = expectThrows(ExecutionException.class, () -> acquirePrimaryOperationPermitBlockingly(shard));
assertThat(e.getCause(), instanceOf(ShardNotInPrimaryModeException.class));
assertThat(e.getCause(), hasToString(containsString("shard is not in primary mode")));
closeShards(shard);
}
Aggregations