54
54
import org .elasticsearch .cluster .routing .RecoverySource .SnapshotRecoverySource ;
55
55
import org .elasticsearch .cluster .routing .ShardRouting ;
56
56
import org .elasticsearch .common .Booleans ;
57
+ import org .elasticsearch .common .CheckedConsumer ;
57
58
import org .elasticsearch .common .CheckedFunction ;
58
59
import org .elasticsearch .common .CheckedRunnable ;
59
60
import org .elasticsearch .common .Nullable ;
@@ -1787,34 +1788,38 @@ public ShardPath shardPath() {
1787
1788
return path ;
1788
1789
}
1789
1790
1790
- public boolean recoverFromLocalShards (BiConsumer <String , MappingMetaData > mappingUpdateConsumer ,
1791
- List < IndexShard > localShards ) throws IOException {
1791
+ public void recoverFromLocalShards (BiConsumer <String , MappingMetaData > mappingUpdateConsumer , List < IndexShard > localShards ,
1792
+ ActionListener < Boolean > listener ) throws IOException {
1792
1793
assert shardRouting .primary () : "recover from local shards only makes sense if the shard is a primary shard" ;
1793
1794
assert recoveryState .getRecoverySource ().getType () == RecoverySource .Type .LOCAL_SHARDS : "invalid recovery type: " +
1794
1795
recoveryState .getRecoverySource ();
1795
1796
final List <LocalShardSnapshot > snapshots = new ArrayList <>();
1797
+ final ActionListener <Boolean > recoveryListener = ActionListener .runBefore (listener , () -> IOUtils .close (snapshots ));
1798
+ boolean success = false ;
1796
1799
try {
1797
1800
for (IndexShard shard : localShards ) {
1798
1801
snapshots .add (new LocalShardSnapshot (shard ));
1799
1802
}
1800
-
1801
1803
// we are the first primary, recover from the gateway
1802
1804
// if its post api allocation, the index should exists
1803
1805
assert shardRouting .primary () : "recover from local shards only makes sense if the shard is a primary shard" ;
1804
1806
StoreRecovery storeRecovery = new StoreRecovery (shardId , logger );
1805
- return storeRecovery .recoverFromLocalShards (mappingUpdateConsumer , this , snapshots );
1807
+ storeRecovery .recoverFromLocalShards (mappingUpdateConsumer , this , snapshots , recoveryListener );
1808
+ success = true ;
1806
1809
} finally {
1807
- IOUtils .close (snapshots );
1810
+ if (success == false ) {
1811
+ IOUtils .close (snapshots );
1812
+ }
1808
1813
}
1809
1814
}
1810
1815
1811
- public boolean recoverFromStore () {
1816
+ public void recoverFromStore (ActionListener < Boolean > listener ) {
1812
1817
// we are the first primary, recover from the gateway
1813
1818
// if its post api allocation, the index should exists
1814
1819
assert shardRouting .primary () : "recover from store only makes sense if the shard is a primary shard" ;
1815
1820
assert shardRouting .initializing () : "can only start recovery on initializing shard" ;
1816
1821
StoreRecovery storeRecovery = new StoreRecovery (shardId , logger );
1817
- return storeRecovery .recoverFromStore (this );
1822
+ storeRecovery .recoverFromStore (this , listener );
1818
1823
}
1819
1824
1820
1825
public void restoreFromRepository (Repository repository , ActionListener <Boolean > listener ) {
@@ -2484,17 +2489,7 @@ public void startRecovery(RecoveryState recoveryState, PeerRecoveryTargetService
2484
2489
switch (recoveryState .getRecoverySource ().getType ()) {
2485
2490
case EMPTY_STORE :
2486
2491
case EXISTING_STORE :
2487
- markAsRecovering ("from store" , recoveryState ); // mark the shard as recovering on the cluster state thread
2488
- threadPool .generic ().execute (() -> {
2489
- try {
2490
- if (recoverFromStore ()) {
2491
- recoveryListener .onRecoveryDone (recoveryState );
2492
- }
2493
- } catch (Exception e ) {
2494
- recoveryListener .onRecoveryFailure (recoveryState ,
2495
- new RecoveryFailedException (recoveryState , null , e ), true );
2496
- }
2497
- });
2492
+ executeRecovery ("from store" , recoveryState , recoveryListener , this ::recoverFromStore );
2498
2493
break ;
2499
2494
case PEER :
2500
2495
try {
@@ -2507,17 +2502,9 @@ public void startRecovery(RecoveryState recoveryState, PeerRecoveryTargetService
2507
2502
}
2508
2503
break ;
2509
2504
case SNAPSHOT :
2510
- markAsRecovering ("from snapshot" , recoveryState ); // mark the shard as recovering on the cluster state thread
2511
- SnapshotRecoverySource recoverySource = (SnapshotRecoverySource ) recoveryState .getRecoverySource ();
2512
- threadPool .generic ().execute (
2513
- ActionRunnable .<Boolean >wrap (ActionListener .wrap (r -> {
2514
- if (r ) {
2515
- recoveryListener .onRecoveryDone (recoveryState );
2516
- }
2517
- },
2518
- e -> recoveryListener .onRecoveryFailure (recoveryState , new RecoveryFailedException (recoveryState , null , e ), true )),
2519
- restoreListener -> restoreFromRepository (
2520
- repositoriesService .repository (recoverySource .snapshot ().getRepository ()), restoreListener )));
2505
+ final String repo = ((SnapshotRecoverySource ) recoveryState .getRecoverySource ()).snapshot ().getRepository ();
2506
+ executeRecovery ("from snapshot" ,
2507
+ recoveryState , recoveryListener , l -> restoreFromRepository (repositoriesService .repository (repo ), l ));
2521
2508
break ;
2522
2509
case LOCAL_SHARDS :
2523
2510
final IndexMetaData indexMetaData = indexSettings ().getIndexMetaData ();
@@ -2542,18 +2529,9 @@ public void startRecovery(RecoveryState recoveryState, PeerRecoveryTargetService
2542
2529
2543
2530
if (numShards == startedShards .size ()) {
2544
2531
assert requiredShards .isEmpty () == false ;
2545
- markAsRecovering ("from local shards" , recoveryState ); // mark the shard as recovering on the cluster state thread
2546
- threadPool .generic ().execute (() -> {
2547
- try {
2548
- if (recoverFromLocalShards (mappingUpdateConsumer , startedShards .stream ()
2549
- .filter ((s ) -> requiredShards .contains (s .shardId ())).collect (Collectors .toList ()))) {
2550
- recoveryListener .onRecoveryDone (recoveryState );
2551
- }
2552
- } catch (Exception e ) {
2553
- recoveryListener .onRecoveryFailure (recoveryState ,
2554
- new RecoveryFailedException (recoveryState , null , e ), true );
2555
- }
2556
- });
2532
+ executeRecovery ("from local shards" , recoveryState , recoveryListener ,
2533
+ l -> recoverFromLocalShards (mappingUpdateConsumer ,
2534
+ startedShards .stream ().filter ((s ) -> requiredShards .contains (s .shardId ())).collect (Collectors .toList ()), l ));
2557
2535
} else {
2558
2536
final RuntimeException e ;
2559
2537
if (numShards == -1 ) {
@@ -2571,6 +2549,17 @@ public void startRecovery(RecoveryState recoveryState, PeerRecoveryTargetService
2571
2549
}
2572
2550
}
2573
2551
2552
+ private void executeRecovery (String reason , RecoveryState recoveryState , PeerRecoveryTargetService .RecoveryListener recoveryListener ,
2553
+ CheckedConsumer <ActionListener <Boolean >, Exception > action ) {
2554
+ markAsRecovering (reason , recoveryState ); // mark the shard as recovering on the cluster state thread
2555
+ threadPool .generic ().execute (ActionRunnable .wrap (ActionListener .wrap (r -> {
2556
+ if (r ) {
2557
+ recoveryListener .onRecoveryDone (recoveryState );
2558
+ }
2559
+ },
2560
+ e -> recoveryListener .onRecoveryFailure (recoveryState , new RecoveryFailedException (recoveryState , null , e ), true )), action ));
2561
+ }
2562
+
2574
2563
/**
2575
2564
* Returns whether the shard is a relocated primary, i.e. not in charge anymore of replicating changes (see {@link ReplicationTracker}).
2576
2565
*/
0 commit comments