/** * Acquires a permit whenever permit acquisition is not blocked. If the permit is directly available, the provided * {@link ActionListener} will be called on the calling thread. During calls of * {@link #blockOperations(long, TimeUnit, CheckedRunnable)}, permit acquisition can be delayed. * The {@link ActionListener#onResponse(Object)} method will then be called using the provided executor once operations are no * longer blocked. Note that the executor will not be used for {@link ActionListener#onFailure(Exception)} calls. Those will run * directly on the calling thread, which in case of delays, will be a generic thread. Callers should thus make sure * that the {@link ActionListener#onFailure(Exception)} method provided here only contains lightweight operations. * * @param onAcquired {@link ActionListener} that is invoked once acquisition is successful or failed * @param executorOnDelay executor to use for the possibly delayed {@link ActionListener#onResponse(Object)} call * @param forceExecution whether the runnable should force its execution in case it gets rejected * @param debugInfo an extra information that can be useful when tracing an unreleased permit. When assertions are enabled * the tracing will capture the supplied object's {@link Object#toString()} value. Otherwise the object * isn't used * */ public void acquire(final ActionListener<Releasable> onAcquired, final String executorOnDelay, final boolean forceExecution, final Object debugInfo) { final StackTraceElement[] stackTrace; if (Assertions.ENABLED) { stackTrace = Thread.currentThread().getStackTrace(); } else { stackTrace = null; } acquire(onAcquired, executorOnDelay, forceExecution, debugInfo, stackTrace); }
assert operationPrimaryTerm <= pendingPrimaryTerm; final CountDownLatch termUpdated = new CountDownLatch(1); indexShardOperationPermits.asyncBlockOperations(new ActionListener<Releasable>() { @Override public void onFailure(final Exception e) {
public void close(String reason, boolean flushEngine) throws IOException { synchronized (mutex) { try { changeState(IndexShardState.CLOSED, reason); } finally { final Engine engine = this.currentEngineReference.getAndSet(null); try { if (engine != null && flushEngine) { engine.flushAndClose(); } } finally { // playing safe here and close the engine even if the above succeeds - close can be called multiple times // Also closing refreshListeners to prevent us from accumulating any more listeners IOUtils.close(engine, globalCheckpointListeners, refreshListeners); indexShardOperationPermits.close(); } } } }
/** * Wait for in-flight operations to finish and executes {@code onBlocked} under the guarantee that no new operations are started. Queues * operations that are occurring in the meanwhile and runs them once {@code onBlocked} has executed. * * @param timeout the maximum time to wait for the in-flight operations block * @param timeUnit the time unit of the {@code timeout} argument * @param onBlocked the action to run once the block has been acquired * @param <E> the type of checked exception thrown by {@code onBlocked} * @throws InterruptedException if calling thread is interrupted * @throws TimeoutException if timed out waiting for in-flight operations to finish * @throws IndexShardClosedException if operation permit has been closed */ <E extends Exception> void blockOperations( final long timeout, final TimeUnit timeUnit, final CheckedRunnable<E> onBlocked) throws InterruptedException, TimeoutException, E { delayOperations(); try (Releasable ignored = acquireAll(timeout, timeUnit)) { onBlocked.run(); } finally { releaseDelayedOperations(); } }
/** * Wait for in-flight operations to finish and executes {@code onBlocked} under the guarantee that no new operations are started. Queues * operations that are occurring in the meanwhile and runs them once {@code onBlocked} has executed. * * @param timeout the maximum time to wait for the in-flight operations block * @param timeUnit the time unit of the {@code timeout} argument * @param onBlocked the action to run once the block has been acquired * @param <E> the type of checked exception thrown by {@code onBlocked} * @throws InterruptedException if calling thread is interrupted * @throws TimeoutException if timed out waiting for in-flight operations to finish * @throws IndexShardClosedException if operation permit has been closed */ <E extends Exception> void blockOperations( final long timeout, final TimeUnit timeUnit, final CheckedRunnable<E> onBlocked) throws InterruptedException, TimeoutException, E { delayOperations(); try { doBlockOperations(timeout, timeUnit, onBlocked); } finally { releaseDelayedOperations(); } }
assert shardRouting.primary() : "only primaries can be marked as relocated: " + shardRouting; try { indexShardOperationPermits.blockOperations(30, TimeUnit.MINUTES, () -> { assert indexShardOperationPermits.getActiveOperationsCount() == 0 : "in-flight operations in progress while moving shard state to relocated";
delayOperations(); threadPool.executor(ThreadPool.Names.GENERIC).execute(new AbstractRunnable() {
cachingPolicy = new UsageTrackingQueryCachingPolicy(); indexShardOperationPermits = new IndexShardOperationPermits(shardId, logger, threadPool); searcherWrapper = indexSearcherWrapper; pendingPrimaryTerm = indexSettings.getIndexMetaData().primaryTerm(shardId.id());
this.indexShardOperationPermits.isBlocked() || // if permits are blocked, we are still transitioning this.replicationTracker.isPrimaryMode() : "a started primary with non-pending operation term must be in primary mode " + this.shardRouting;
/** * @return a list of describing each permit that wasn't released yet. The description consist of the debugInfo supplied * when the permit was acquired plus a stack traces that was captured when the permit was request. */ public List<String> getActiveOperations() { return indexShardOperationPermits.getActiveOperations(); }
public int getActiveOperationsCount() { // refCount is incremented on successful acquire and decremented on close return indexShardOperationPermits.getActiveOperationsCount(); }
assert shardRouting.primary() : "only primaries can be marked as relocated: " + shardRouting; try { indexShardOperationPermits.blockOperations(30, TimeUnit.MINUTES, () -> {
/** * Wait for in-flight operations to finish and executes {@code onBlocked} under the guarantee that no new operations are started. Queues * operations that are occurring in the meanwhile and runs them once {@code onBlocked} has executed. * * @param timeout the maximum time to wait for the in-flight operations block * @param timeUnit the time unit of the {@code timeout} argument * @param onBlocked the action to run once the block has been acquired * @param <E> the type of checked exception thrown by {@code onBlocked} * @throws InterruptedException if calling thread is interrupted * @throws TimeoutException if timed out waiting for in-flight operations to finish * @throws IndexShardClosedException if operation permit has been closed */ <E extends Exception> void blockOperations( final long timeout, final TimeUnit timeUnit, final CheckedRunnable<E> onBlocked) throws InterruptedException, TimeoutException, E { delayOperations(); try { doBlockOperations(timeout, timeUnit, onBlocked); } finally { releaseDelayedOperations(); } }
assert shardRouting.primary() : "only primaries can be marked as relocated: " + shardRouting; try { indexShardOperationPermits.blockOperations(30, TimeUnit.MINUTES, () -> { assert indexShardOperationPermits.getActiveOperationsCount() == 0 : "in-flight operations in progress while moving shard state to relocated";
/** * Immediately delays operations and on another thread waits for in-flight operations to finish and then executes {@code onBlocked} * under the guarantee that no new operations are started. Delayed operations are run after {@code onBlocked} has executed. After * operations are delayed and the blocking is forked to another thread, returns to the caller. If a failure occurs while blocking * operations or executing {@code onBlocked} then the {@code onFailure} handler will be invoked. * * @param timeout the maximum time to wait for the in-flight operations block * @param timeUnit the time unit of the {@code timeout} argument * @param onBlocked the action to run once the block has been acquired * @param onFailure the action to run if a failure occurs while blocking operations * @param <E> the type of checked exception thrown by {@code onBlocked} (not thrown on the calling thread) */ <E extends Exception> void asyncBlockOperations( final long timeout, final TimeUnit timeUnit, final CheckedRunnable<E> onBlocked, final Consumer<Exception> onFailure) { delayOperations(); threadPool.executor(ThreadPool.Names.GENERIC).execute(new AbstractRunnable() { @Override public void onFailure(final Exception e) { onFailure.accept(e); } @Override protected void doRun() throws Exception { doBlockOperations(timeout, timeUnit, onBlocked); } @Override public void onAfter() { releaseDelayedOperations(); } }); }
cachingPolicy = new UsageTrackingQueryCachingPolicy(); indexShardOperationPermits = new IndexShardOperationPermits(shardId, logger, threadPool); searcherWrapper = indexSearcherWrapper; pendingPrimaryTerm = indexSettings.getIndexMetaData().primaryTerm(shardId.id());
this.indexShardOperationPermits.isBlocked() || // if permits are blocked, we are still transitioning this.replicationTracker.isPrimaryMode() : "a started primary with non-pending operation term must be in primary mode " + this.shardRouting;
/** * @return a list of describing each permit that wasn't released yet. The description consist of the debugInfo supplied * when the permit was acquired plus a stack traces that was captured when the permit was request. */ public List<String> getActiveOperations() { return indexShardOperationPermits.getActiveOperations(); }
public int getActiveOperationsCount() { return indexShardOperationPermits.getActiveOperationsCount(); // refCount is incremented on successful acquire and decremented on close }
/** * Acquire a replica operation permit whenever the shard is ready for indexing (see * {@link #acquirePrimaryOperationPermit(ActionListener, String, Object)}). If the given primary term is lower than then one in * {@link #shardRouting}, the {@link ActionListener#onFailure(Exception)} method of the provided listener is invoked with an * {@link IllegalStateException}. If permit acquisition is delayed, the listener will be invoked on the executor with the specified * name. * * @param opPrimaryTerm the operation primary term * @param globalCheckpoint the global checkpoint associated with the request * @param maxSeqNoOfUpdatesOrDeletes the max seq_no of updates (index operations overwrite Lucene) or deletes captured on the primary * after this replication request was executed on it (see {@link #getMaxSeqNoOfUpdatesOrDeletes()} * @param onPermitAcquired the listener for permit acquisition * @param executorOnDelay the name of the executor to invoke the listener on if permit acquisition is delayed * @param debugInfo an extra information that can be useful when tracing an unreleased permit. When assertions are * enabled the tracing will capture the supplied object's {@link Object#toString()} value. * Otherwise the object isn't used */ public void acquireReplicaOperationPermit(final long opPrimaryTerm, final long globalCheckpoint, final long maxSeqNoOfUpdatesOrDeletes, final ActionListener<Releasable> onPermitAcquired, final String executorOnDelay, final Object debugInfo) { innerAcquireReplicaOperationPermit(opPrimaryTerm, globalCheckpoint, maxSeqNoOfUpdatesOrDeletes, onPermitAcquired, false, (listener) -> indexShardOperationPermits.acquire(listener, executorOnDelay, true, debugInfo)); }