|
34 | 34 | import org.elasticsearch.action.admin.indices.flush.FlushRequest; |
35 | 35 | import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeRequest; |
36 | 36 | import org.elasticsearch.action.support.PlainActionFuture; |
| 37 | +import org.elasticsearch.action.support.RefCountingListener; |
37 | 38 | import org.elasticsearch.action.support.SubscribableListener; |
38 | 39 | import org.elasticsearch.action.support.replication.PendingReplicationActions; |
39 | 40 | import org.elasticsearch.action.support.replication.ReplicationResponse; |
|
189 | 190 | import static org.elasticsearch.core.Strings.format; |
190 | 191 | import static org.elasticsearch.index.seqno.RetentionLeaseActions.RETAIN_ALL; |
191 | 192 | import static org.elasticsearch.index.seqno.SequenceNumbers.UNASSIGNED_SEQ_NO; |
192 | | -import static org.elasticsearch.index.shard.IndexShard.PrimaryPermitCheck.CHECK_PRIMARY_MODE; |
193 | 193 |
|
194 | 194 | public class IndexShard extends AbstractIndexShardComponent implements IndicesClusterStateService.Shard { |
195 | 195 |
|
@@ -779,28 +779,10 @@ public void relocated( |
779 | 779 | final String targetAllocationId, |
780 | 780 | final BiConsumer<ReplicationTracker.PrimaryContext, ActionListener<Void>> consumer, |
781 | 781 | final ActionListener<Void> listener |
782 | | - ) throws IllegalIndexShardStateException, IllegalStateException { |
783 | | - relocated(targetNodeId, targetAllocationId, consumer, listener, null); |
784 | | - } |
785 | | - |
786 | | - /** |
787 | | - * Provides an variant of {@link IndexShard#relocated(String, String, BiConsumer, ActionListener, Releasable)} with an option |
788 | | - * to relocate the shard under externally acquired primary permits. |
789 | | - * |
790 | | - * @param acquiredPrimaryPermits if null, waits until all the primary permits are acquired, otherwise it calls the consumer immediately |
791 | | - */ |
792 | | - public void relocated( |
793 | | - final String targetNodeId, |
794 | | - final String targetAllocationId, |
795 | | - final BiConsumer<ReplicationTracker.PrimaryContext, ActionListener<Void>> consumer, |
796 | | - final ActionListener<Void> listener, |
797 | | - @Nullable final Releasable acquiredPrimaryPermits |
798 | 782 | ) throws IllegalIndexShardStateException, IllegalStateException { |
799 | 783 | assert shardRouting.primary() : "only primaries can be marked as relocated: " + shardRouting; |
800 | | - assert acquiredPrimaryPermits == null || indexShardOperationPermits.getActiveOperationsCount() == OPERATIONS_BLOCKED |
801 | | - : "external primary permits are provided but not held by the shard"; |
802 | 784 | try (Releasable forceRefreshes = refreshListeners.forceRefreshes()) { |
803 | | - ActionListener<Releasable> onAcquired = new ActionListener<>() { |
| 785 | + indexShardOperationPermits.blockOperations(new ActionListener<>() { |
804 | 786 | @Override |
805 | 787 | public void onResponse(Releasable releasable) { |
806 | 788 | boolean success = false; |
@@ -878,13 +860,8 @@ public void onFailure(Exception e) { |
878 | 860 | listener.onFailure(e); |
879 | 861 | } |
880 | 862 | } |
881 | | - }; |
882 | | - if (acquiredPrimaryPermits == null) { |
883 | | - // Wait on current thread because this execution is wrapped by CancellableThreads and we want to be able to interrupt it |
884 | | - indexShardOperationPermits.blockOperations(onAcquired, 30L, TimeUnit.MINUTES, EsExecutors.DIRECT_EXECUTOR_SERVICE); |
885 | | - } else { |
886 | | - ActionListener.completeWith(onAcquired, () -> acquiredPrimaryPermits); |
887 | | - } |
| 863 | + }, 30L, TimeUnit.MINUTES, EsExecutors.DIRECT_EXECUTOR_SERVICE); // Wait on current thread because this execution is wrapped by |
| 864 | + // CancellableThreads and we want to be able to interrupt it |
888 | 865 | } |
889 | 866 | } |
890 | 867 |
|
@@ -3592,100 +3569,69 @@ private EngineConfig newEngineConfig(LongSupplier globalCheckpointSupplier) { |
3592 | 3569 | ); |
3593 | 3570 | } |
3594 | 3571 |
|
3595 | | - /** |
3596 | | - * Check to run before running the primary permit operation |
3597 | | - */ |
3598 | | - public enum PrimaryPermitCheck { |
3599 | | - CHECK_PRIMARY_MODE, |
3600 | | - /** |
3601 | | - * IMPORTANT: Currently intented to be used only for acquiring primary permits during the recovery of hollow shards. |
3602 | | - * Don't disable primary mode checks unless you're really sure. |
3603 | | - */ |
3604 | | - NONE |
3605 | | - } |
3606 | | - |
3607 | 3572 | /** |
3608 | 3573 | * Acquire a primary operation permit whenever the shard is ready for indexing. If a permit is directly available, the provided |
3609 | 3574 | * ActionListener will be called on the calling thread. During relocation hand-off, permit acquisition can be delayed. The provided |
3610 | 3575 | * ActionListener will then be called using the provided executor. |
3611 | 3576 | */ |
3612 | 3577 | public void acquirePrimaryOperationPermit(ActionListener<Releasable> onPermitAcquired, Executor executorOnDelay) { |
3613 | | - acquirePrimaryOperationPermit(onPermitAcquired, executorOnDelay, false, CHECK_PRIMARY_MODE); |
| 3578 | + acquirePrimaryOperationPermit(onPermitAcquired, executorOnDelay, false); |
3614 | 3579 | } |
3615 | 3580 |
|
3616 | 3581 | public void acquirePrimaryOperationPermit( |
3617 | 3582 | ActionListener<Releasable> onPermitAcquired, |
3618 | 3583 | Executor executorOnDelay, |
3619 | 3584 | boolean forceExecution |
3620 | | - ) { |
3621 | | - acquirePrimaryOperationPermit(onPermitAcquired, executorOnDelay, forceExecution, CHECK_PRIMARY_MODE); |
3622 | | - } |
3623 | | - |
3624 | | - public void acquirePrimaryOperationPermit( |
3625 | | - ActionListener<Releasable> onPermitAcquired, |
3626 | | - Executor executorOnDelay, |
3627 | | - boolean forceExecution, |
3628 | | - PrimaryPermitCheck primaryPermitCheck |
3629 | 3585 | ) { |
3630 | 3586 | verifyNotClosed(); |
3631 | 3587 | assert shardRouting.primary() : "acquirePrimaryOperationPermit should only be called on primary shard: " + shardRouting; |
3632 | | - indexShardOperationPermits.acquire( |
3633 | | - wrapPrimaryOperationPermitListener(primaryPermitCheck, onPermitAcquired), |
3634 | | - executorOnDelay, |
3635 | | - forceExecution |
3636 | | - ); |
| 3588 | + |
| 3589 | + ActionListener<Releasable> onPermitAcquiredWrapped = onPermitAcquired.delegateFailureAndWrap((delegate, releasable) -> { |
| 3590 | + final ActionListener<Releasable> wrappedListener = indexShardOperationPermits.wrapContextPreservingActionListener( |
| 3591 | + delegate, |
| 3592 | + executorOnDelay, |
| 3593 | + forceExecution |
| 3594 | + ); |
| 3595 | + try (var listeners = new RefCountingListener(wrappedListener.map(unused -> releasable))) { |
| 3596 | + indexEventListener.onAcquirePrimaryOperationPermit(this, () -> listeners.acquire()); |
| 3597 | + } |
| 3598 | + }); |
| 3599 | + |
| 3600 | + indexShardOperationPermits.acquire(wrapPrimaryOperationPermitListener(onPermitAcquiredWrapped), executorOnDelay, forceExecution); |
3637 | 3601 | } |
3638 | 3602 |
|
3639 | 3603 | public boolean isPrimaryMode() { |
3640 | 3604 | assert indexShardOperationPermits.getActiveOperationsCount() != 0 : "must hold permit to check primary mode"; |
3641 | 3605 | return replicationTracker.isPrimaryMode(); |
3642 | 3606 | } |
3643 | 3607 |
|
3644 | | - public void acquireAllPrimaryOperationsPermits(final ActionListener<Releasable> onPermitAcquired, final TimeValue timeout) { |
3645 | | - acquireAllPrimaryOperationsPermits(onPermitAcquired, timeout, CHECK_PRIMARY_MODE); |
3646 | | - } |
3647 | | - |
3648 | 3608 | /** |
3649 | 3609 | * Acquire all primary operation permits. Once all permits are acquired, the provided ActionListener is called. |
3650 | 3610 | * It is the responsibility of the caller to close the {@link Releasable}. |
3651 | 3611 | */ |
3652 | | - public void acquireAllPrimaryOperationsPermits( |
3653 | | - final ActionListener<Releasable> onPermitAcquired, |
3654 | | - final TimeValue timeout, |
3655 | | - final PrimaryPermitCheck primaryPermitCheck |
3656 | | - ) { |
| 3612 | + public void acquireAllPrimaryOperationsPermits(final ActionListener<Releasable> onPermitAcquired, final TimeValue timeout) { |
3657 | 3613 | verifyNotClosed(); |
3658 | 3614 | assert shardRouting.primary() : "acquireAllPrimaryOperationsPermits should only be called on primary shard: " + shardRouting; |
3659 | 3615 |
|
3660 | | - asyncBlockOperations( |
3661 | | - wrapPrimaryOperationPermitListener(primaryPermitCheck, onPermitAcquired), |
3662 | | - timeout.duration(), |
3663 | | - timeout.timeUnit() |
3664 | | - ); |
| 3616 | + asyncBlockOperations(wrapPrimaryOperationPermitListener(onPermitAcquired), timeout.duration(), timeout.timeUnit()); |
3665 | 3617 | } |
3666 | 3618 |
|
3667 | 3619 | /** |
3668 | | - * Wraps the action to run on a primary after acquiring permit. |
| 3620 | + * Wraps the action to run on a primary after acquiring permit. This wrapping is used to check if the shard is in primary mode before |
| 3621 | + * executing the action. |
3669 | 3622 | * |
3670 | | - * @param primaryPermitCheck check to run before the primary mode operation |
3671 | 3623 | * @param listener the listener to wrap |
3672 | 3624 | * @return the wrapped listener |
3673 | 3625 | */ |
3674 | | - private ActionListener<Releasable> wrapPrimaryOperationPermitListener( |
3675 | | - final PrimaryPermitCheck primaryPermitCheck, |
3676 | | - final ActionListener<Releasable> listener |
3677 | | - ) { |
3678 | | - return switch (primaryPermitCheck) { |
3679 | | - case CHECK_PRIMARY_MODE -> listener.delegateFailure((l, r) -> { |
3680 | | - if (isPrimaryMode()) { |
3681 | | - l.onResponse(r); |
3682 | | - } else { |
3683 | | - r.close(); |
3684 | | - l.onFailure(new ShardNotInPrimaryModeException(shardId, state)); |
3685 | | - } |
3686 | | - }); |
3687 | | - case NONE -> listener; |
3688 | | - }; |
| 3626 | + private ActionListener<Releasable> wrapPrimaryOperationPermitListener(final ActionListener<Releasable> listener) { |
| 3627 | + return listener.delegateFailure((l, r) -> { |
| 3628 | + if (isPrimaryMode()) { |
| 3629 | + l.onResponse(r); |
| 3630 | + } else { |
| 3631 | + r.close(); |
| 3632 | + l.onFailure(new ShardNotInPrimaryModeException(shardId, state)); |
| 3633 | + } |
| 3634 | + }); |
3689 | 3635 | } |
3690 | 3636 |
|
3691 | 3637 | private void asyncBlockOperations(ActionListener<Releasable> onPermitAcquired, long timeout, TimeUnit timeUnit) { |
@@ -3723,7 +3669,7 @@ public void runUnderPrimaryPermit(final Runnable runnable, final Consumer<Except |
3723 | 3669 | runnable.run(); |
3724 | 3670 | } |
3725 | 3671 | }, onFailure); |
3726 | | - acquirePrimaryOperationPermit(onPermitAcquired, executorOnDelay, false, CHECK_PRIMARY_MODE); |
| 3672 | + acquirePrimaryOperationPermit(onPermitAcquired, executorOnDelay); |
3727 | 3673 | } |
3728 | 3674 |
|
3729 | 3675 | private <E extends Exception> void bumpPrimaryTerm( |
|
0 commit comments