Skip to content

Commit 96e2d27

Browse files
committed
Fix the translog operation asserter to check for map equivalence rather than byte per byte if fields are synthetic
1 parent 87c5d57 commit 96e2d27

File tree

2 files changed

+48
-15
lines changed

2 files changed

+48
-15
lines changed

server/src/main/java/org/elasticsearch/index/engine/TranslogOperationAsserter.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ public boolean assertSameIndexOperation(Translog.Index o1, Translog.Index o2) th
4141
if (engineConfig.getIndexSettings().isRecoverySourceSyntheticEnabled()
4242
|| engineConfig.getMapperService().mappingLookup().inferenceFields().isEmpty() == false
4343
|| engineConfig.getMapperService().mappingLookup().syntheticVectorFields().isEmpty() == false) {
44-
return super.assertSameIndexOperation(synthesizeSource(engineConfig, o1), o2)
45-
|| super.assertSameIndexOperation(o1, synthesizeSource(engineConfig, o2));
44+
// for synthetic source and synthetic fields, we check that the resulting source map is equivalent
45+
// since ordering might not be preserved.
46+
return Translog.Index.equalsWithoutAutoGeneratedTimestamp(synthesizeSource(engineConfig, o1), o2, false)
47+
|| Translog.Index.equalsWithoutAutoGeneratedTimestamp(o1, synthesizeSource(engineConfig, o2), false);
4648
}
4749
return false;
4850
}
@@ -99,6 +101,6 @@ static Translog.Snapshot newSnapshot(EngineConfig engineConfig, Translog.Index o
99101
}
100102

101103
public boolean assertSameIndexOperation(Translog.Index o1, Translog.Index o2) throws IOException {
102-
return Translog.Index.equalsWithoutAutoGeneratedTimestamp(o1, o2);
104+
return Translog.Index.equalsWithoutAutoGeneratedTimestamp(o1, o2, true);
103105
}
104106
}

server/src/main/java/org/elasticsearch/index/translog/Translog.java

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.elasticsearch.common.io.stream.Writeable;
2323
import org.elasticsearch.common.lucene.uid.Versions;
2424
import org.elasticsearch.common.util.BigArrays;
25+
import org.elasticsearch.common.xcontent.XContentHelper;
2526
import org.elasticsearch.core.IOUtils;
2627
import org.elasticsearch.core.Nullable;
2728
import org.elasticsearch.core.Releasable;
@@ -35,6 +36,8 @@
3536
import org.elasticsearch.index.shard.AbstractIndexShardComponent;
3637
import org.elasticsearch.index.shard.IndexShardComponent;
3738
import org.elasticsearch.index.shard.ShardId;
39+
import org.elasticsearch.search.lookup.Source;
40+
import org.elasticsearch.xcontent.XContentParserConfiguration;
3841

3942
import java.io.Closeable;
4043
import java.io.EOFException;
@@ -1226,9 +1229,9 @@ public Type opType() {
12261229
@Override
12271230
public long estimateSize() {
12281231
return (2 * id.length()) + source.length() + (routing != null ? 2 * routing.length() : 0) + (4 * Long.BYTES); // timestamp,
1229-
// seq_no,
1230-
// primary_term,
1231-
// and version
1232+
// seq_no,
1233+
// primary_term,
1234+
// and version
12321235
}
12331236

12341237
public String id() {
@@ -1275,7 +1278,7 @@ public boolean equals(Object o) {
12751278
}
12761279

12771280
Index other = (Index) o;
1278-
return autoGeneratedIdTimestamp == other.autoGeneratedIdTimestamp && equalsWithoutAutoGeneratedTimestamp(this, other);
1281+
return autoGeneratedIdTimestamp == other.autoGeneratedIdTimestamp && equalsWithoutAutoGeneratedTimestamp(this, other, true);
12791282
}
12801283

12811284
@Override
@@ -1311,15 +1314,43 @@ public long getAutoGeneratedIdTimestamp() {
13111314
return autoGeneratedIdTimestamp;
13121315
}
13131316

1314-
public static boolean equalsWithoutAutoGeneratedTimestamp(Translog.Index o1, Translog.Index o2) {
1315-
return o1.version == o2.version
1316-
&& o1.seqNo == o2.seqNo
1317-
&& o1.primaryTerm == o2.primaryTerm
1318-
&& o1.id.equals(o2.id)
1319-
&& o1.source.equals(o2.source)
1320-
&& Objects.equals(o1.routing, o2.routing);
1321-
}
1317+
public static boolean equalsWithoutAutoGeneratedTimestamp(Translog.Index o1, Translog.Index o2, boolean checkSourceBytes) {
1318+
if (o1.version != o2.version
1319+
|| o1.seqNo != o2.seqNo
1320+
|| o1.primaryTerm != o2.primaryTerm
1321+
|| o1.id.equals(o2.id) == false
1322+
|| Objects.equals(o1.routing, o2.routing) == false) {
1323+
return false;
1324+
}
1325+
1326+
if (checkSourceBytes) {
1327+
return o1.source.equals(o2.source);
1328+
}
13221329

1330+
var s1 = Source.fromBytes(o1.source);
1331+
var s2 = Source.fromBytes(o2.source);
1332+
try (
1333+
var actualParser = XContentHelper.createParserNotCompressed(
1334+
XContentParserConfiguration.EMPTY,
1335+
s1.internalSourceRef(),
1336+
s1.sourceContentType()
1337+
)
1338+
) {
1339+
var actualMap = actualParser.map();
1340+
try (
1341+
var expectedParser = XContentHelper.createParserNotCompressed(
1342+
XContentParserConfiguration.EMPTY,
1343+
s2.internalSourceRef(),
1344+
s2.sourceContentType()
1345+
)
1346+
) {
1347+
var expectedMap = expectedParser.map();
1348+
return expectedMap.equals(actualMap);
1349+
}
1350+
} catch (IOException exc) {
1351+
return false;
1352+
}
1353+
}
13231354
}
13241355

13251356
public static final class Delete extends Operation {

0 commit comments

Comments
 (0)