79
79
import java .util .Objects ;
80
80
import java .util .Set ;
81
81
import java .util .concurrent .BlockingQueue ;
82
+ import java .util .concurrent .CompletableFuture ;
82
83
import java .util .concurrent .ConcurrentLinkedDeque ;
83
84
import java .util .concurrent .CopyOnWriteArrayList ;
84
85
import java .util .concurrent .LinkedBlockingQueue ;
@@ -199,7 +200,12 @@ public void recoverToTarget(ActionListener<RecoveryResponse> listener) {
199
200
retentionLeaseRef .set (
200
201
shard .getRetentionLeases ().get (ReplicationTracker .getPeerRecoveryRetentionLeaseId (targetShardRouting ))
201
202
);
202
- }, shardId + " validating recovery target [" + request .targetAllocationId () + "] registered " , shard , cancellableThreads );
203
+ },
204
+ shardId + " validating recovery target [" + request .targetAllocationId () + "] registered " ,
205
+ shard ,
206
+ cancellableThreads ,
207
+ logger
208
+ );
203
209
final Closeable retentionLock = shard .acquireHistoryRetentionLock ();
204
210
resources .add (retentionLock );
205
211
final long startingSeqNo ;
@@ -286,7 +292,7 @@ && isTargetSameHistory()
286
292
logger .debug ("no peer-recovery retention lease for " + request .targetAllocationId ());
287
293
deleteRetentionLeaseStep .onResponse (null );
288
294
}
289
- }, shardId + " removing retention lease for [" + request .targetAllocationId () + "]" , shard , cancellableThreads );
295
+ }, shardId + " removing retention lease for [" + request .targetAllocationId () + "]" , shard , cancellableThreads , logger );
290
296
291
297
deleteRetentionLeaseStep .whenComplete (ignored -> {
292
298
assert Transports .assertNotTransportThread (RecoverySourceHandler .this + "[phase1]" );
@@ -317,7 +323,8 @@ && isTargetSameHistory()
317
323
() -> shard .initiateTracking (request .targetAllocationId ()),
318
324
shardId + " initiating tracking of " + request .targetAllocationId (),
319
325
shard ,
320
- cancellableThreads
326
+ cancellableThreads ,
327
+ logger
321
328
);
322
329
323
330
final long endingSeqNo = shard .seqNoStats ().getMaxSeqNo ();
@@ -398,21 +405,44 @@ static void runUnderPrimaryPermit(
398
405
CancellableThreads .Interruptible runnable ,
399
406
String reason ,
400
407
IndexShard primary ,
401
- CancellableThreads cancellableThreads
408
+ CancellableThreads cancellableThreads ,
409
+ Logger logger
402
410
) {
403
411
cancellableThreads .execute (() -> {
404
- final var permit = new ListenableActionFuture <Releasable >();
405
- primary .acquirePrimaryOperationPermit (permit , ThreadPool .Names .SAME , reason );
406
- try (var ignored = FutureUtils .get (permit )) {
412
+ CompletableFuture <Releasable > permit = new CompletableFuture <>();
413
+
414
+ // this wrapping looks unnecessary necessary, see #93290; TODO remove it
415
+ final ActionListener <Releasable > onAcquired = new ActionListener <Releasable >() {
416
+ @ Override
417
+ public void onResponse (Releasable releasable ) {
418
+ if (permit .complete (releasable ) == false ) {
419
+ releasable .close ();
420
+ }
421
+ }
422
+
423
+ @ Override
424
+ public void onFailure (Exception e ) {
425
+ permit .completeExceptionally (e );
426
+ }
427
+ };
428
+ primary .acquirePrimaryOperationPermit (onAcquired , ThreadPool .Names .SAME , reason );
429
+ try (Releasable ignored = FutureUtils .get (permit )) {
407
430
// check that the IndexShard still has the primary authority. This needs to be checked under operation permit to prevent
408
431
// races, as IndexShard will switch its authority only when it holds all operation permits, see IndexShard.relocated()
409
432
if (primary .isRelocatedPrimary ()) {
410
433
throw new IndexShardRelocatedException (primary .shardId ());
411
434
}
412
435
runnable .run ();
413
436
} finally {
414
- // add a listener to release the permit because we might have been interrupted while waiting (double-releasing is ok)
415
- permit .addListener (ActionListener .wrap (Releasable ::close , e -> {}));
437
+ // just in case we got an exception (likely interrupted) while waiting for the get
438
+ permit .whenComplete ((r , e ) -> {
439
+ if (r != null ) {
440
+ r .close ();
441
+ }
442
+ if (e != null ) {
443
+ logger .trace ("suppressing exception on completion (it was already bubbled up or the operation was aborted)" , e );
444
+ }
445
+ });
416
446
}
417
447
});
418
448
}
@@ -980,7 +1010,7 @@ void createRetentionLease(final long startingSeqNo, ActionListener<RetentionLeas
980
1010
addRetentionLeaseStep .addListener (listener .map (rr -> newLease ));
981
1011
logger .trace ("created retention lease with estimated checkpoint of [{}]" , estimatedGlobalCheckpoint );
982
1012
}
983
- }, shardId + " establishing retention lease for [" + request .targetAllocationId () + "]" , shard , cancellableThreads );
1013
+ }, shardId + " establishing retention lease for [" + request .targetAllocationId () + "]" , shard , cancellableThreads , logger );
984
1014
}
985
1015
986
1016
boolean hasSameLegacySyncId (Store .MetadataSnapshot source , Store .MetadataSnapshot target ) {
@@ -1221,7 +1251,8 @@ void finalizeRecovery(long targetLocalCheckpoint, long trimAboveSeqNo, ActionLis
1221
1251
() -> shard .markAllocationIdAsInSync (request .targetAllocationId (), targetLocalCheckpoint ),
1222
1252
shardId + " marking " + request .targetAllocationId () + " as in sync" ,
1223
1253
shard ,
1224
- cancellableThreads
1254
+ cancellableThreads ,
1255
+ logger
1225
1256
);
1226
1257
final long globalCheckpoint = shard .getLastKnownGlobalCheckpoint (); // this global checkpoint is persisted in finalizeRecovery
1227
1258
final StepListener <Void > finalizeListener = new StepListener <>();
@@ -1232,7 +1263,8 @@ void finalizeRecovery(long targetLocalCheckpoint, long trimAboveSeqNo, ActionLis
1232
1263
() -> shard .updateGlobalCheckpointForShard (request .targetAllocationId (), globalCheckpoint ),
1233
1264
shardId + " updating " + request .targetAllocationId () + "'s global checkpoint" ,
1234
1265
shard ,
1235
- cancellableThreads
1266
+ cancellableThreads ,
1267
+ logger
1236
1268
);
1237
1269
1238
1270
if (request .isPrimaryRelocation ()) {
0 commit comments