/** * 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); }
/** * 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)); }
private void releaseDelayedOperations() { final List<DelayedOperation> queuedActions; synchronized (this) { assert queuedBlockOperations > 0; queuedBlockOperations--; if (queuedBlockOperations == 0) { queuedActions = new ArrayList<>(delayedOperations); delayedOperations.clear(); } else { queuedActions = Collections.emptyList(); } } if (!queuedActions.isEmpty()) { /* * Try acquiring permits on fresh thread (for two reasons): * - blockOperations can be called on a recovery thread which can be expected to be interrupted when recovery is cancelled; * interruptions are bad here as permit acquisition will throw an interrupted exception which will be swallowed by * the threaded action listener if the queue of the thread pool on which it submits is full * - if a permit is acquired and the queue of the thread pool which the threaded action listener uses is full, the * onFailure handler is executed on the calling thread; this should not be the recovery thread as it would delay the * recovery */ threadPool.executor(ThreadPool.Names.GENERIC).execute(() -> { for (DelayedOperation queuedAction : queuedActions) { acquire(queuedAction.listener, null, false, queuedAction.debugInfo, queuedAction.stackTrace); } }); } }
/** * Acquire a primary operation permit whenever the shard is ready for indexing. If a permit is directly available, the provided * ActionListener will be called on the calling thread. During relocation hand-off, permit acquisition can be delayed. The provided * ActionListener will then be called using the provided executor. * * @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 acquirePrimaryOperationPermit(ActionListener<Releasable> onPermitAcquired, String executorOnDelay, Object debugInfo) { verifyNotClosed(); assert shardRouting.primary() : "acquirePrimaryOperationPermit should only be called on primary shard: " + shardRouting; indexShardOperationPermits.acquire(onPermitAcquired, executorOnDelay, false, debugInfo); }
return; } else { releasable = acquire(debugInfo, stackTrace);
/** * 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); }
/** * 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); }
private void releaseDelayedOperations() { final List<DelayedOperation> queuedActions; synchronized (this) { assert queuedBlockOperations > 0; queuedBlockOperations--; if (queuedBlockOperations == 0) { queuedActions = new ArrayList<>(delayedOperations); delayedOperations.clear(); } else { queuedActions = Collections.emptyList(); } } if (!queuedActions.isEmpty()) { /* * Try acquiring permits on fresh thread (for two reasons): * - blockOperations can be called on a recovery thread which can be expected to be interrupted when recovery is cancelled; * interruptions are bad here as permit acquisition will throw an interrupted exception which will be swallowed by * the threaded action listener if the queue of the thread pool on which it submits is full * - if a permit is acquired and the queue of the thread pool which the threaded action listener uses is full, the * onFailure handler is executed on the calling thread; this should not be the recovery thread as it would delay the * recovery */ threadPool.executor(ThreadPool.Names.GENERIC).execute(() -> { for (DelayedOperation queuedAction : queuedActions) { acquire(queuedAction.listener, null, false, queuedAction.debugInfo, queuedAction.stackTrace); } }); } }
private void releaseDelayedOperations() { final List<DelayedOperation> queuedActions; synchronized (this) { assert queuedBlockOperations > 0; queuedBlockOperations--; if (queuedBlockOperations == 0) { queuedActions = new ArrayList<>(delayedOperations); delayedOperations.clear(); } else { queuedActions = Collections.emptyList(); } } if (!queuedActions.isEmpty()) { /* * Try acquiring permits on fresh thread (for two reasons): * - blockOperations can be called on a recovery thread which can be expected to be interrupted when recovery is cancelled; * interruptions are bad here as permit acquisition will throw an interrupted exception which will be swallowed by * the threaded action listener if the queue of the thread pool on which it submits is full * - if a permit is acquired and the queue of the thread pool which the threaded action listener uses is full, the * onFailure handler is executed on the calling thread; this should not be the recovery thread as it would delay the * recovery */ threadPool.executor(ThreadPool.Names.GENERIC).execute(() -> { for (DelayedOperation queuedAction : queuedActions) { acquire(queuedAction.listener, null, false, queuedAction.debugInfo, queuedAction.stackTrace); } }); } }
/** * Acquire a primary operation permit whenever the shard is ready for indexing. If a permit is directly available, the provided * ActionListener will be called on the calling thread. During relocation hand-off, permit acquisition can be delayed. The provided * ActionListener will then be called using the provided executor. * * @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 acquirePrimaryOperationPermit(ActionListener<Releasable> onPermitAcquired, String executorOnDelay, Object debugInfo) { verifyNotClosed(); assert shardRouting.primary() : "acquirePrimaryOperationPermit should only be called on primary shard: " + shardRouting; indexShardOperationPermits.acquire(onPermitAcquired, executorOnDelay, false, debugInfo); }
return; } else { releasable = acquire(debugInfo, stackTrace);
return; } else { releasable = acquire(debugInfo, stackTrace);
indexShardOperationPermits.acquire( new ActionListener<Releasable>() { @Override