use of org.opensearch.common.util.concurrent.RunOnce in project OpenSearch by opensearch-project.
the class MappingUpdatedAction method updateMappingOnMaster.
/**
* Update mappings on the master node, waiting for the change to be committed,
* but not for the mapping update to be applied on all nodes. The timeout specified by
* {@code timeout} is the master node timeout ({@link MasterNodeRequest#masterNodeTimeout()}),
* potentially waiting for a master node to be available.
*/
public void updateMappingOnMaster(Index index, Mapping mappingUpdate, ActionListener<Void> listener) {
final RunOnce release = new RunOnce(() -> semaphore.release());
try {
semaphore.acquire();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
listener.onFailure(e);
return;
}
boolean successFullySent = false;
try {
sendUpdateMapping(index, mappingUpdate, ActionListener.runBefore(listener, release::run));
successFullySent = true;
} finally {
if (successFullySent == false) {
release.run();
}
}
}
use of org.opensearch.common.util.concurrent.RunOnce in project OpenSearch by opensearch-project.
the class IndexShard method bumpPrimaryTerm.
private <E extends Exception> void bumpPrimaryTerm(final long newPrimaryTerm, final CheckedRunnable<E> onBlocked, @Nullable ActionListener<Releasable> combineWithAction) {
assert Thread.holdsLock(mutex);
assert newPrimaryTerm > pendingPrimaryTerm || (newPrimaryTerm >= pendingPrimaryTerm && combineWithAction != null);
assert getOperationPrimaryTerm() <= pendingPrimaryTerm;
final CountDownLatch termUpdated = new CountDownLatch(1);
asyncBlockOperations(new ActionListener<Releasable>() {
@Override
public void onFailure(final Exception e) {
try {
innerFail(e);
} finally {
if (combineWithAction != null) {
combineWithAction.onFailure(e);
}
}
}
private void innerFail(final Exception e) {
try {
failShard("exception during primary term transition", e);
} catch (AlreadyClosedException ace) {
// ignore, shard is already closed
}
}
@Override
public void onResponse(final Releasable releasable) {
final RunOnce releaseOnce = new RunOnce(releasable::close);
try {
assert getOperationPrimaryTerm() <= pendingPrimaryTerm;
termUpdated.await();
// in the order submitted. We need to guard against another term bump
if (getOperationPrimaryTerm() < newPrimaryTerm) {
replicationTracker.setOperationPrimaryTerm(newPrimaryTerm);
onBlocked.run();
}
} catch (final Exception e) {
if (combineWithAction == null) {
// otherwise leave it to combineWithAction to release the permit
releaseOnce.run();
}
innerFail(e);
} finally {
if (combineWithAction != null) {
combineWithAction.onResponse(releasable);
} else {
releaseOnce.run();
}
}
}
}, 30, TimeUnit.MINUTES);
pendingPrimaryTerm = newPrimaryTerm;
termUpdated.countDown();
}
use of org.opensearch.common.util.concurrent.RunOnce in project OpenSearch by opensearch-project.
the class IndexShardOperationPermits method asyncBlockOperations.
/**
* Immediately delays operations and on another thread waits for in-flight operations to finish and then acquires all permits. When all
* permits are acquired, the provided {@link ActionListener} is called under the guarantee that no new operations are started. Delayed
* operations are run once the {@link Releasable} is released or if a failure occurs while acquiring all permits; in this case the
* {@code onFailure} handler will be invoked after delayed operations are released.
*
* @param onAcquired {@link ActionListener} that is invoked once acquisition is successful or failed
* @param timeout the maximum time to wait for the in-flight operations block
* @param timeUnit the time unit of the {@code timeout} argument
*/
public void asyncBlockOperations(final ActionListener<Releasable> onAcquired, final long timeout, final TimeUnit timeUnit) {
delayOperations();
threadPool.executor(ThreadPool.Names.GENERIC).execute(new AbstractRunnable() {
final RunOnce released = new RunOnce(() -> releaseDelayedOperations());
@Override
public void onFailure(final Exception e) {
try {
// resume delayed operations as soon as possible
released.run();
} finally {
onAcquired.onFailure(e);
}
}
@Override
protected void doRun() throws Exception {
final Releasable releasable = acquireAll(timeout, timeUnit);
onAcquired.onResponse(() -> {
try {
releasable.close();
} finally {
released.run();
}
});
}
});
}
use of org.opensearch.common.util.concurrent.RunOnce in project OpenSearch by opensearch-project.
the class WorkerBulkByScrollTaskState method delayPrepareBulkRequest.
/**
* Schedule prepareBulkRequestRunnable to run after some delay. This is where throttling plugs into reindexing so the request can be
* rescheduled over and over again.
*/
public void delayPrepareBulkRequest(ThreadPool threadPool, long lastBatchStartTimeNS, int lastBatchSize, AbstractRunnable prepareBulkRequestRunnable) {
// Synchronize so we are less likely to schedule the same request twice.
synchronized (delayedPrepareBulkRequestReference) {
TimeValue delay = throttleWaitTime(lastBatchStartTimeNS, System.nanoTime(), lastBatchSize);
logger.debug("[{}]: preparing bulk request for [{}]", task.getId(), delay);
try {
delayedPrepareBulkRequestReference.set(new DelayedPrepareBulkRequest(threadPool, getRequestsPerSecond(), delay, new RunOnce(prepareBulkRequestRunnable)));
} catch (OpenSearchRejectedExecutionException e) {
prepareBulkRequestRunnable.onRejection(e);
}
}
}
use of org.opensearch.common.util.concurrent.RunOnce in project OpenSearch by opensearch-project.
the class ReopenWhileClosingIT method interceptVerifyShardBeforeCloseActions.
/**
* Intercepts and blocks the {@link TransportVerifyShardBeforeCloseAction} executed for the given index pattern.
*/
private Releasable interceptVerifyShardBeforeCloseActions(final String indexPattern, final Runnable onIntercept) {
final MockTransportService mockTransportService = (MockTransportService) internalCluster().getInstance(TransportService.class, internalCluster().getMasterName());
final CountDownLatch release = new CountDownLatch(1);
for (DiscoveryNode node : internalCluster().clusterService().state().getNodes()) {
mockTransportService.addSendBehavior(internalCluster().getInstance(TransportService.class, node.getName()), (connection, requestId, action, request, options) -> {
if (action.startsWith(TransportVerifyShardBeforeCloseAction.NAME)) {
if (request instanceof TransportVerifyShardBeforeCloseAction.ShardRequest) {
final String index = ((TransportVerifyShardBeforeCloseAction.ShardRequest) request).shardId().getIndexName();
if (Glob.globMatch(indexPattern, index)) {
logger.info("request {} intercepted for index {}", requestId, index);
onIntercept.run();
try {
release.await();
logger.info("request {} released for index {}", requestId, index);
} catch (final InterruptedException e) {
throw new AssertionError(e);
}
}
}
}
connection.sendRequest(requestId, action, request, options);
});
}
final RunOnce releaseOnce = new RunOnce(release::countDown);
return releaseOnce::run;
}
Aggregations