Use correct primary term for replicating NOOPs (#25128)

NOOPs should be, same as for indexing operations, written on the replica using the original operation term instead of the current term of the replica.
This commit is contained in:
Yannick Welsch 2017-06-08 14:20:26 +02:00 committed by GitHub
parent 326fa33d4e
commit cd57395c98
7 changed files with 17 additions and 11 deletions

View File

@ -477,7 +477,7 @@ public class TransportShardBulkAction extends TransportWriteAction<BulkShardRequ
case FAILURE: case FAILURE:
final BulkItemResponse.Failure failure = item.getPrimaryResponse().getFailure(); final BulkItemResponse.Failure failure = item.getPrimaryResponse().getFailure();
assert failure.getSeqNo() != SequenceNumbersService.UNASSIGNED_SEQ_NO : "seq no must be assigned"; assert failure.getSeqNo() != SequenceNumbersService.UNASSIGNED_SEQ_NO : "seq no must be assigned";
operationResult = executeFailureNoOpOnReplica(failure, replica); operationResult = executeFailureNoOpOnReplica(failure, primaryTerm, replica);
assert operationResult != null : "operation result must never be null when primary response has no failure"; assert operationResult != null : "operation result must never be null when primary response has no failure";
location = syncOperationResultOrThrow(operationResult, location); location = syncOperationResultOrThrow(operationResult, location);
break; break;
@ -673,9 +673,10 @@ public class TransportShardBulkAction extends TransportWriteAction<BulkShardRequ
return replica.delete(delete); return replica.delete(delete);
} }
private static Engine.NoOpResult executeFailureNoOpOnReplica(BulkItemResponse.Failure primaryFailure, IndexShard replica) throws IOException { private static Engine.NoOpResult executeFailureNoOpOnReplica(BulkItemResponse.Failure primaryFailure, long primaryTerm,
final Engine.NoOp noOp = replica.prepareMarkingSeqNoAsNoOp( IndexShard replica) throws IOException {
primaryFailure.getSeqNo(), primaryFailure.getMessage()); final Engine.NoOp noOp = replica.prepareMarkingSeqNoAsNoOpOnReplica(
primaryFailure.getSeqNo(), primaryTerm, primaryFailure.getMessage());
return replica.markSeqNoAsNoOp(noOp); return replica.markSeqNoAsNoOp(noOp);
} }

View File

@ -628,10 +628,11 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
return result; return result;
} }
public Engine.NoOp prepareMarkingSeqNoAsNoOp(long seqNo, String reason) { public Engine.NoOp prepareMarkingSeqNoAsNoOpOnReplica(long seqNo, long opPrimaryTerm, String reason) {
verifyReplicationTarget(); verifyReplicationTarget();
assert opPrimaryTerm <= this.primaryTerm : "op term [ " + opPrimaryTerm + " ] > shard term [" + this.primaryTerm + "]";
long startTime = System.nanoTime(); long startTime = System.nanoTime();
return new Engine.NoOp(seqNo, primaryTerm, Engine.Operation.Origin.REPLICA, startTime, reason); return new Engine.NoOp(seqNo, opPrimaryTerm, Engine.Operation.Origin.REPLICA, startTime, reason);
} }
public Engine.NoOpResult markSeqNoAsNoOp(Engine.NoOp noOp) throws IOException { public Engine.NoOpResult markSeqNoAsNoOp(Engine.NoOp noOp) throws IOException {

View File

@ -541,11 +541,13 @@ public class TransportShardBulkActionTests extends IndexShardTestCase {
itemRequests[0] = itemRequest; itemRequests[0] = itemRequest;
BulkShardRequest bulkShardRequest = new BulkShardRequest( BulkShardRequest bulkShardRequest = new BulkShardRequest(
shard.shardId(), RefreshPolicy.NONE, itemRequests); shard.shardId(), RefreshPolicy.NONE, itemRequests);
bulkShardRequest.primaryTerm(randomIntBetween(1, (int) shard.getPrimaryTerm()));
TransportShardBulkAction.performOnReplica(bulkShardRequest, shard); TransportShardBulkAction.performOnReplica(bulkShardRequest, shard);
ArgumentCaptor<Engine.NoOp> noOp = ArgumentCaptor.forClass(Engine.NoOp.class); ArgumentCaptor<Engine.NoOp> noOp = ArgumentCaptor.forClass(Engine.NoOp.class);
verify(shard, times(1)).markSeqNoAsNoOp(noOp.capture()); verify(shard, times(1)).markSeqNoAsNoOp(noOp.capture());
final Engine.NoOp noOpValue = noOp.getValue(); final Engine.NoOp noOpValue = noOp.getValue();
assertThat(noOpValue.seqNo(), equalTo(1L)); assertThat(noOpValue.seqNo(), equalTo(1L));
assertThat(noOpValue.primaryTerm(), equalTo(bulkShardRequest.primaryTerm()));
assertThat(noOpValue.reason(), containsString(failureMessage)); assertThat(noOpValue.reason(), containsString(failureMessage));
closeShards(shard); closeShards(shard);
} }

View File

@ -105,7 +105,7 @@ public abstract class ESIndexLevelReplicationTestCase extends IndexShardTestCase
.build(); .build();
IndexMetaData.Builder metaData = IndexMetaData.builder(index.getName()) IndexMetaData.Builder metaData = IndexMetaData.builder(index.getName())
.settings(settings) .settings(settings)
.primaryTerm(0, 1); .primaryTerm(0, randomIntBetween(1, 100));
for (Map.Entry<String, String> typeMapping : mappings.entrySet()) { for (Map.Entry<String, String> typeMapping : mappings.entrySet()) {
metaData.putMapping(typeMapping.getKey(), typeMapping.getValue()); metaData.putMapping(typeMapping.getKey(), typeMapping.getValue());
} }

View File

@ -238,7 +238,7 @@ public class IndexLevelReplicationTests extends ESIndexLevelReplicationTestCase
.source("{}", XContentType.JSON) .source("{}", XContentType.JSON)
); );
assertTrue(response.isFailed()); assertTrue(response.isFailed());
assertNoOpTranslogOperationForDocumentFailure(shards, 1, failureMessage); assertNoOpTranslogOperationForDocumentFailure(shards, 1, shards.getPrimary().getPrimaryTerm(), failureMessage);
shards.assertAllEqual(0); shards.assertAllEqual(0);
// add some replicas // add some replicas
@ -252,7 +252,7 @@ public class IndexLevelReplicationTests extends ESIndexLevelReplicationTestCase
.source("{}", XContentType.JSON) .source("{}", XContentType.JSON)
); );
assertTrue(response.isFailed()); assertTrue(response.isFailed());
assertNoOpTranslogOperationForDocumentFailure(shards, 2, failureMessage); assertNoOpTranslogOperationForDocumentFailure(shards, 2, shards.getPrimary().getPrimaryTerm(), failureMessage);
shards.assertAllEqual(0); shards.assertAllEqual(0);
} }
} }
@ -323,6 +323,7 @@ public class IndexLevelReplicationTests extends ESIndexLevelReplicationTestCase
private static void assertNoOpTranslogOperationForDocumentFailure( private static void assertNoOpTranslogOperationForDocumentFailure(
Iterable<IndexShard> replicationGroup, Iterable<IndexShard> replicationGroup,
int expectedOperation, int expectedOperation,
long expectedPrimaryTerm,
String failureMessage) throws IOException { String failureMessage) throws IOException {
for (IndexShard indexShard : replicationGroup) { for (IndexShard indexShard : replicationGroup) {
try(Translog.View view = indexShard.acquireTranslogView()) { try(Translog.View view = indexShard.acquireTranslogView()) {
@ -333,6 +334,7 @@ public class IndexLevelReplicationTests extends ESIndexLevelReplicationTestCase
do { do {
assertThat(op.opType(), equalTo(Translog.Operation.Type.NO_OP)); assertThat(op.opType(), equalTo(Translog.Operation.Type.NO_OP));
assertThat(op.seqNo(), equalTo(expectedSeqNo)); assertThat(op.seqNo(), equalTo(expectedSeqNo));
assertThat(op.primaryTerm(), equalTo(expectedPrimaryTerm));
assertThat(((Translog.NoOp) op).reason(), containsString(failureMessage)); assertThat(((Translog.NoOp) op).reason(), containsString(failureMessage));
op = snapshot.next(); op = snapshot.next();
expectedSeqNo++; expectedSeqNo++;

View File

@ -1281,7 +1281,7 @@ public class IndexShardTests extends IndexShardTestCase {
while((operation = snapshot.next()) != null) { while((operation = snapshot.next()) != null) {
if (operation.opType() == Translog.Operation.Type.NO_OP) { if (operation.opType() == Translog.Operation.Type.NO_OP) {
numNoops++; numNoops++;
assertEquals(1, operation.primaryTerm()); assertEquals(newShard.getPrimaryTerm(), operation.primaryTerm());
assertEquals(0, operation.seqNo()); assertEquals(0, operation.seqNo());
} }
} }

View File

@ -159,7 +159,7 @@ public abstract class IndexShardTestCase extends ESTestCase {
.build(); .build();
IndexMetaData.Builder metaData = IndexMetaData.builder(shardRouting.getIndexName()) IndexMetaData.Builder metaData = IndexMetaData.builder(shardRouting.getIndexName())
.settings(settings) .settings(settings)
.primaryTerm(0, 1); .primaryTerm(0, randomIntBetween(1, 100));
return newShard(shardRouting, metaData.build(), listeners); return newShard(shardRouting, metaData.build(), listeners);
} }