Skip to content

Commit 2b1d1cb

Browse files
committed
Fix primary relocation for shadow replicas (#22474)
The recovery process started during primary relocation of shadow replicas accesses the engine on the source shard after it's been closed, which results in the source shard failing itself.
1 parent d8d7b69 commit 2b1d1cb

File tree

3 files changed

+8
-5
lines changed

3 files changed

+8
-5
lines changed

core/src/main/java/org/elasticsearch/indices/recovery/RecoverySourceHandler.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ public void phase1(final IndexCommit snapshot, final Translog.View translogView)
329329
}
330330
}
331331

332-
prepareTargetForTranslog(translogView.totalOperations());
332+
prepareTargetForTranslog(translogView.totalOperations(), shard.segmentStats(false).getMaxUnsafeAutoIdTimestamp());
333333

334334
logger.trace("[{}][{}] recovery [phase1] to {}: took [{}]", indexName, shardId, request.targetNode(), stopWatch.totalTime());
335335
response.phase1Time = stopWatch.totalTime().millis();
@@ -341,15 +341,14 @@ public void phase1(final IndexCommit snapshot, final Translog.View translogView)
341341
}
342342

343343

344-
protected void prepareTargetForTranslog(final int totalTranslogOps) throws IOException {
344+
protected void prepareTargetForTranslog(final int totalTranslogOps, long maxUnsafeAutoIdTimestamp) throws IOException {
345345
StopWatch stopWatch = new StopWatch().start();
346346
logger.trace("{} recovery [phase1] to {}: prepare remote engine for translog", request.shardId(), request.targetNode());
347347
final long startEngineStart = stopWatch.totalTime().millis();
348348
// Send a request preparing the new shard's translog to receive
349349
// operations. This ensures the shard engine is started and disables
350350
// garbage collection (not the JVM's GC!) of tombstone deletes
351-
cancellableThreads.executeIO(() -> recoveryTarget.prepareForTranslogOperations(totalTranslogOps,
352-
shard.segmentStats(false).getMaxUnsafeAutoIdTimestamp()));
351+
cancellableThreads.executeIO(() -> recoveryTarget.prepareForTranslogOperations(totalTranslogOps, maxUnsafeAutoIdTimestamp));
353352
stopWatch.stop();
354353

355354
response.startTime = stopWatch.totalTime().millis() - startEngineStart;

core/src/main/java/org/elasticsearch/indices/recovery/SharedFSRecoverySourceHandler.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ public RecoveryResponse recoverToTarget() throws IOException {
5050
boolean engineClosed = false;
5151
try {
5252
logger.trace("{} recovery [phase1] to {}: skipping phase 1 for shared filesystem", request.shardId(), request.targetNode());
53+
long maxUnsafeAutoIdTimestamp = shard.segmentStats(false).getMaxUnsafeAutoIdTimestamp();
5354
if (request.isPrimaryRelocation()) {
5455
logger.debug("[phase1] closing engine on primary for shared filesystem recovery");
5556
try {
@@ -62,7 +63,7 @@ public RecoveryResponse recoverToTarget() throws IOException {
6263
shard.failShard("failed to close engine (phase1)", e);
6364
}
6465
}
65-
prepareTargetForTranslog(0);
66+
prepareTargetForTranslog(0, maxUnsafeAutoIdTimestamp);
6667
finalizeRecovery();
6768
return response;
6869
} catch (Exception e) {

core/src/test/java/org/elasticsearch/index/IndexWithShadowReplicasIT.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,9 @@ public void testPrimaryRelocation() throws Exception {
359359
client().admin().indices().prepareUpdateSettings(IDX).setSettings(build).execute().actionGet();
360360

361361
ensureGreen(IDX);
362+
// check if primary has relocated to node3
363+
assertEquals(internalCluster().clusterService(node3).localNode().getId(),
364+
client().admin().cluster().prepareState().get().getState().routingTable().index(IDX).shard(0).primaryShard().currentNodeId());
362365
logger.info("--> performing query");
363366
SearchResponse resp = client().prepareSearch(IDX).setQuery(matchAllQuery()).get();
364367
assertHitCount(resp, 2);

0 commit comments

Comments
 (0)