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 ;
@@ -1821,34 +1822,38 @@ public ShardPath shardPath() {
1821
1822
return path ;
1822
1823
}
1823
1824
1824
- public boolean recoverFromLocalShards (BiConsumer <String , MappingMetaData > mappingUpdateConsumer ,
1825
- List < IndexShard > localShards ) throws IOException {
1825
+ public void recoverFromLocalShards (BiConsumer <String , MappingMetaData > mappingUpdateConsumer , List < IndexShard > localShards ,
1826
+ ActionListener < Boolean > listener ) throws IOException {
1826
1827
assert shardRouting .primary () : "recover from local shards only makes sense if the shard is a primary shard" ;
1827
1828
assert recoveryState .getRecoverySource ().getType () == RecoverySource .Type .LOCAL_SHARDS : "invalid recovery type: " +
1828
1829
recoveryState .getRecoverySource ();
1829
1830
final List <LocalShardSnapshot > snapshots = new ArrayList <>();
1831
+ final ActionListener <Boolean > recoveryListener = ActionListener .runBefore (listener , () -> IOUtils .close (snapshots ));
1832
+ boolean success = false ;
1830
1833
try {
1831
1834
for (IndexShard shard : localShards ) {
1832
1835
snapshots .add (new LocalShardSnapshot (shard ));
1833
1836
}
1834
-
1835
1837
// we are the first primary, recover from the gateway
1836
1838
// if its post api allocation, the index should exists
1837
1839
assert shardRouting .primary () : "recover from local shards only makes sense if the shard is a primary shard" ;
1838
1840
StoreRecovery storeRecovery = new StoreRecovery (shardId , logger );
1839
- return storeRecovery .recoverFromLocalShards (mappingUpdateConsumer , this , snapshots );
1841
+ storeRecovery .recoverFromLocalShards (mappingUpdateConsumer , this , snapshots , recoveryListener );
1842
+ success = true ;
1840
1843
} finally {
1841
- IOUtils .close (snapshots );
1844
+ if (success == false ) {
1845
+ IOUtils .close (snapshots );
1846
+ }
1842
1847
}
1843
1848
}
1844
1849
1845
- public boolean recoverFromStore () {
1850
+ public void recoverFromStore (ActionListener < Boolean > listener ) {
1846
1851
// we are the first primary, recover from the gateway
1847
1852
// if its post api allocation, the index should exists
1848
1853
assert shardRouting .primary () : "recover from store only makes sense if the shard is a primary shard" ;
1849
1854
assert shardRouting .initializing () : "can only start recovery on initializing shard" ;
1850
1855
StoreRecovery storeRecovery = new StoreRecovery (shardId , logger );
1851
- return storeRecovery .recoverFromStore (this );
1856
+ storeRecovery .recoverFromStore (this , listener );
1852
1857
}
1853
1858
1854
1859
public void restoreFromRepository (Repository repository , ActionListener <Boolean > listener ) {
@@ -2520,17 +2525,7 @@ public void startRecovery(RecoveryState recoveryState, PeerRecoveryTargetService
2520
2525
switch (recoveryState .getRecoverySource ().getType ()) {
2521
2526
case EMPTY_STORE :
2522
2527
case EXISTING_STORE :
2523
- markAsRecovering ("from store" , recoveryState ); // mark the shard as recovering on the cluster state thread
2524
- threadPool .generic ().execute (() -> {
2525
- try {
2526
- if (recoverFromStore ()) {
2527
- recoveryListener .onRecoveryDone (recoveryState );
2528
- }
2529
- } catch (Exception e ) {
2530
- recoveryListener .onRecoveryFailure (recoveryState ,
2531
- new RecoveryFailedException (recoveryState , null , e ), true );
2532
- }
2533
- });
2528
+ executeRecovery ("from store" , recoveryState , recoveryListener , this ::recoverFromStore );
2534
2529
break ;
2535
2530
case PEER :
2536
2531
try {
@@ -2543,17 +2538,9 @@ public void startRecovery(RecoveryState recoveryState, PeerRecoveryTargetService
2543
2538
}
2544
2539
break ;
2545
2540
case SNAPSHOT :
2546
- markAsRecovering ("from snapshot" , recoveryState ); // mark the shard as recovering on the cluster state thread
2547
- SnapshotRecoverySource recoverySource = (SnapshotRecoverySource ) recoveryState .getRecoverySource ();
2548
- threadPool .generic ().execute (
2549
- ActionRunnable .<Boolean >wrap (ActionListener .wrap (r -> {
2550
- if (r ) {
2551
- recoveryListener .onRecoveryDone (recoveryState );
2552
- }
2553
- },
2554
- e -> recoveryListener .onRecoveryFailure (recoveryState , new RecoveryFailedException (recoveryState , null , e ), true )),
2555
- restoreListener -> restoreFromRepository (
2556
- repositoriesService .repository (recoverySource .snapshot ().getRepository ()), restoreListener )));
2541
+ final String repo = ((SnapshotRecoverySource ) recoveryState .getRecoverySource ()).snapshot ().getRepository ();
2542
+ executeRecovery ("from snapshot" ,
2543
+ recoveryState , recoveryListener , l -> restoreFromRepository (repositoriesService .repository (repo ), l ));
2557
2544
break ;
2558
2545
case LOCAL_SHARDS :
2559
2546
final IndexMetaData indexMetaData = indexSettings ().getIndexMetaData ();
@@ -2578,18 +2565,9 @@ public void startRecovery(RecoveryState recoveryState, PeerRecoveryTargetService
2578
2565
2579
2566
if (numShards == startedShards .size ()) {
2580
2567
assert requiredShards .isEmpty () == false ;
2581
- markAsRecovering ("from local shards" , recoveryState ); // mark the shard as recovering on the cluster state thread
2582
- threadPool .generic ().execute (() -> {
2583
- try {
2584
- if (recoverFromLocalShards (mappingUpdateConsumer , startedShards .stream ()
2585
- .filter ((s ) -> requiredShards .contains (s .shardId ())).collect (Collectors .toList ()))) {
2586
- recoveryListener .onRecoveryDone (recoveryState );
2587
- }
2588
- } catch (Exception e ) {
2589
- recoveryListener .onRecoveryFailure (recoveryState ,
2590
- new RecoveryFailedException (recoveryState , null , e ), true );
2591
- }
2592
- });
2568
+ executeRecovery ("from local shards" , recoveryState , recoveryListener ,
2569
+ l -> recoverFromLocalShards (mappingUpdateConsumer ,
2570
+ startedShards .stream ().filter ((s ) -> requiredShards .contains (s .shardId ())).collect (Collectors .toList ()), l ));
2593
2571
} else {
2594
2572
final RuntimeException e ;
2595
2573
if (numShards == -1 ) {
@@ -2607,6 +2585,17 @@ public void startRecovery(RecoveryState recoveryState, PeerRecoveryTargetService
2607
2585
}
2608
2586
}
2609
2587
2588
+ private void executeRecovery (String reason , RecoveryState recoveryState , PeerRecoveryTargetService .RecoveryListener recoveryListener ,
2589
+ CheckedConsumer <ActionListener <Boolean >, Exception > action ) {
2590
+ markAsRecovering (reason , recoveryState ); // mark the shard as recovering on the cluster state thread
2591
+ threadPool .generic ().execute (ActionRunnable .wrap (ActionListener .wrap (r -> {
2592
+ if (r ) {
2593
+ recoveryListener .onRecoveryDone (recoveryState );
2594
+ }
2595
+ },
2596
+ e -> recoveryListener .onRecoveryFailure (recoveryState , new RecoveryFailedException (recoveryState , null , e ), true )), action ));
2597
+ }
2598
+
2610
2599
/**
2611
2600
* Returns whether the shard is a relocated primary, i.e. not in charge anymore of replicating changes (see {@link ReplicationTracker}).
2612
2601
*/
0 commit comments