From c3f8de527b8295afa07d560f295a24309b668109 Mon Sep 17 00:00:00 2001
From: Anton Persson
Date: Wed, 12 Nov 2025 14:07:19 +0100
Subject: [PATCH 1/8] Decouple DeduplicatingFieldInfoCodec
No codec should extend DeduplicatingFieldInfoCodec, instead always wrap
it.
---
.../org/elasticsearch/index/codec/CodecService.java | 13 ++++---------
.../index/codec/Elasticsearch814Codec.java | 3 ++-
.../index/codec/Elasticsearch816Codec.java | 3 ++-
.../index/codec/Elasticsearch900Codec.java | 3 ++-
.../index/codec/Elasticsearch900Lucene101Codec.java | 3 ++-
.../index/codec/Elasticsearch92Lucene103Codec.java | 3 ++-
6 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/server/src/main/java/org/elasticsearch/index/codec/CodecService.java b/server/src/main/java/org/elasticsearch/index/codec/CodecService.java
index 5d6e377d57db9..bee7a1195ffea 100644
--- a/server/src/main/java/org/elasticsearch/index/codec/CodecService.java
+++ b/server/src/main/java/org/elasticsearch/index/codec/CodecService.java
@@ -71,12 +71,7 @@ public CodecService(@Nullable MapperService mapperService, BigArrays bigArrays)
assert useTsdbSyntheticId == false || mapperService.getIndexSettings().getMode() == IndexMode.TIME_SERIES;
this.codecs = codecs.entrySet().stream().collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, e -> {
- Codec codec;
- if (e.getValue() instanceof DeduplicateFieldInfosCodec dedupCodec) {
- codec = dedupCodec;
- } else {
- codec = new DeduplicateFieldInfosCodec(e.getValue().getName(), e.getValue());
- }
+ Codec codec = new DeduplicateFieldInfosCodec(e.getValue().getName(), e.getValue());
if (useTsdbSyntheticId && codec instanceof TSDBSyntheticIdCodec == false) {
codec = new TSDBSyntheticIdCodec(codec.getName(), codec);
}
@@ -100,7 +95,7 @@ public String[] availableCodecs() {
return codecs.keySet().toArray(new String[0]);
}
- public static class DeduplicateFieldInfosCodec extends FilterCodec {
+ public static final class DeduplicateFieldInfosCodec extends FilterCodec {
private final DeduplicatingFieldInfosFormat deduplicatingFieldInfosFormat;
@@ -111,11 +106,11 @@ protected DeduplicateFieldInfosCodec(String name, Codec delegate) {
}
@Override
- public final FieldInfosFormat fieldInfosFormat() {
+ public FieldInfosFormat fieldInfosFormat() {
return deduplicatingFieldInfosFormat;
}
- public final Codec delegate() {
+ public Codec delegate() {
return delegate;
}
diff --git a/server/src/main/java/org/elasticsearch/index/codec/Elasticsearch814Codec.java b/server/src/main/java/org/elasticsearch/index/codec/Elasticsearch814Codec.java
index ae372ea8194bc..08e87f5fe771c 100644
--- a/server/src/main/java/org/elasticsearch/index/codec/Elasticsearch814Codec.java
+++ b/server/src/main/java/org/elasticsearch/index/codec/Elasticsearch814Codec.java
@@ -12,6 +12,7 @@
import org.apache.lucene.backward_codecs.lucene99.Lucene99Codec;
import org.apache.lucene.backward_codecs.lucene99.Lucene99PostingsFormat;
import org.apache.lucene.codecs.DocValuesFormat;
+import org.apache.lucene.codecs.FilterCodec;
import org.apache.lucene.codecs.KnnVectorsFormat;
import org.apache.lucene.codecs.PostingsFormat;
import org.apache.lucene.codecs.StoredFieldsFormat;
@@ -26,7 +27,7 @@
* Elasticsearch codec as of 8.14. This extends the Lucene 9.9 codec to compressed stored fields with ZSTD instead of LZ4/DEFLATE. See
* {@link Zstd814StoredFieldsFormat}.
*/
-public class Elasticsearch814Codec extends CodecService.DeduplicateFieldInfosCodec {
+public class Elasticsearch814Codec extends FilterCodec {
private final StoredFieldsFormat storedFieldsFormat;
diff --git a/server/src/main/java/org/elasticsearch/index/codec/Elasticsearch816Codec.java b/server/src/main/java/org/elasticsearch/index/codec/Elasticsearch816Codec.java
index d58c4e2cdc34a..6060351882042 100644
--- a/server/src/main/java/org/elasticsearch/index/codec/Elasticsearch816Codec.java
+++ b/server/src/main/java/org/elasticsearch/index/codec/Elasticsearch816Codec.java
@@ -12,6 +12,7 @@
import org.apache.lucene.backward_codecs.lucene912.Lucene912Codec;
import org.apache.lucene.backward_codecs.lucene912.Lucene912PostingsFormat;
import org.apache.lucene.codecs.DocValuesFormat;
+import org.apache.lucene.codecs.FilterCodec;
import org.apache.lucene.codecs.KnnVectorsFormat;
import org.apache.lucene.codecs.PostingsFormat;
import org.apache.lucene.codecs.StoredFieldsFormat;
@@ -26,7 +27,7 @@
* Elasticsearch codec as of 8.16. This extends the Lucene 9.12 codec to compressed stored fields with ZSTD instead of LZ4/DEFLATE. See
* {@link Zstd814StoredFieldsFormat}.
*/
-public class Elasticsearch816Codec extends CodecService.DeduplicateFieldInfosCodec {
+public class Elasticsearch816Codec extends FilterCodec {
private static final Lucene912Codec LUCENE_912_CODEC = new Lucene912Codec();
private static final PostingsFormat defaultPostingsFormat = new Lucene912PostingsFormat();
diff --git a/server/src/main/java/org/elasticsearch/index/codec/Elasticsearch900Codec.java b/server/src/main/java/org/elasticsearch/index/codec/Elasticsearch900Codec.java
index 04428d5b37fba..b7590e010ae3d 100644
--- a/server/src/main/java/org/elasticsearch/index/codec/Elasticsearch900Codec.java
+++ b/server/src/main/java/org/elasticsearch/index/codec/Elasticsearch900Codec.java
@@ -12,6 +12,7 @@
import org.apache.lucene.backward_codecs.lucene100.Lucene100Codec;
import org.apache.lucene.backward_codecs.lucene912.Lucene912PostingsFormat;
import org.apache.lucene.codecs.DocValuesFormat;
+import org.apache.lucene.codecs.FilterCodec;
import org.apache.lucene.codecs.KnnVectorsFormat;
import org.apache.lucene.codecs.PostingsFormat;
import org.apache.lucene.codecs.StoredFieldsFormat;
@@ -26,7 +27,7 @@
* Elasticsearch codec as of 9.0-snapshot relying on Lucene 10.0. This extends the Lucene 10.0 codec to compressed stored fields
* with ZSTD instead of LZ4/DEFLATE. See {@link Zstd814StoredFieldsFormat}.
*/
-public class Elasticsearch900Codec extends CodecService.DeduplicateFieldInfosCodec {
+public class Elasticsearch900Codec extends FilterCodec {
private final StoredFieldsFormat storedFieldsFormat;
diff --git a/server/src/main/java/org/elasticsearch/index/codec/Elasticsearch900Lucene101Codec.java b/server/src/main/java/org/elasticsearch/index/codec/Elasticsearch900Lucene101Codec.java
index ad2c40950b6c9..b5eebc7049f42 100644
--- a/server/src/main/java/org/elasticsearch/index/codec/Elasticsearch900Lucene101Codec.java
+++ b/server/src/main/java/org/elasticsearch/index/codec/Elasticsearch900Lucene101Codec.java
@@ -12,6 +12,7 @@
import org.apache.lucene.backward_codecs.lucene101.Lucene101Codec;
import org.apache.lucene.backward_codecs.lucene101.Lucene101PostingsFormat;
import org.apache.lucene.codecs.DocValuesFormat;
+import org.apache.lucene.codecs.FilterCodec;
import org.apache.lucene.codecs.KnnVectorsFormat;
import org.apache.lucene.codecs.PostingsFormat;
import org.apache.lucene.codecs.StoredFieldsFormat;
@@ -26,7 +27,7 @@
* Elasticsearch codec as of 9.0 relying on Lucene 10.1. This extends the Lucene 10.1 codec to compressed
* stored fields with ZSTD instead of LZ4/DEFLATE. See {@link Zstd814StoredFieldsFormat}.
*/
-public class Elasticsearch900Lucene101Codec extends CodecService.DeduplicateFieldInfosCodec {
+public class Elasticsearch900Lucene101Codec extends FilterCodec {
static final PostingsFormat DEFAULT_POSTINGS_FORMAT = new Lucene101PostingsFormat();
diff --git a/server/src/main/java/org/elasticsearch/index/codec/Elasticsearch92Lucene103Codec.java b/server/src/main/java/org/elasticsearch/index/codec/Elasticsearch92Lucene103Codec.java
index c26d485fc8c99..df84581c5c592 100644
--- a/server/src/main/java/org/elasticsearch/index/codec/Elasticsearch92Lucene103Codec.java
+++ b/server/src/main/java/org/elasticsearch/index/codec/Elasticsearch92Lucene103Codec.java
@@ -10,6 +10,7 @@
package org.elasticsearch.index.codec;
import org.apache.lucene.codecs.DocValuesFormat;
+import org.apache.lucene.codecs.FilterCodec;
import org.apache.lucene.codecs.KnnVectorsFormat;
import org.apache.lucene.codecs.PostingsFormat;
import org.apache.lucene.codecs.StoredFieldsFormat;
@@ -26,7 +27,7 @@
* Elasticsearch codec as of 9.2 relying on Lucene 10.3. This extends the Lucene 10.3 codec to compressed
* stored fields with ZSTD instead of LZ4/DEFLATE. See {@link Zstd814StoredFieldsFormat}.
*/
-public class Elasticsearch92Lucene103Codec extends CodecService.DeduplicateFieldInfosCodec {
+public class Elasticsearch92Lucene103Codec extends FilterCodec {
static final PostingsFormat DEFAULT_POSTINGS_FORMAT = new Lucene103PostingsFormat();
From 46c9566c192c3f9947936f25e5edec4275b07448 Mon Sep 17 00:00:00 2001
From: Anton Persson
Date: Wed, 12 Nov 2025 14:09:21 +0100
Subject: [PATCH 2/8] Move DecouplingFieldInfosCodec to upper level
---
.../index/codec/CodecService.java | 22 ------------
.../codec/DeduplicateFieldInfosCodec.java | 35 +++++++++++++++++++
.../mapper/CompletionFieldMapperTests.java | 3 +-
.../vectors/DenseVectorFieldMapperTests.java | 13 +++----
.../codec/GPUDenseVectorFieldMapperTests.java | 3 +-
5 files changed, 46 insertions(+), 30 deletions(-)
create mode 100644 server/src/main/java/org/elasticsearch/index/codec/DeduplicateFieldInfosCodec.java
diff --git a/server/src/main/java/org/elasticsearch/index/codec/CodecService.java b/server/src/main/java/org/elasticsearch/index/codec/CodecService.java
index bee7a1195ffea..5b54a25042233 100644
--- a/server/src/main/java/org/elasticsearch/index/codec/CodecService.java
+++ b/server/src/main/java/org/elasticsearch/index/codec/CodecService.java
@@ -10,8 +10,6 @@
package org.elasticsearch.index.codec;
import org.apache.lucene.codecs.Codec;
-import org.apache.lucene.codecs.FieldInfosFormat;
-import org.apache.lucene.codecs.FilterCodec;
import org.apache.lucene.codecs.lucene103.Lucene103Codec;
import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.common.util.FeatureFlag;
@@ -95,24 +93,4 @@ public String[] availableCodecs() {
return codecs.keySet().toArray(new String[0]);
}
- public static final class DeduplicateFieldInfosCodec extends FilterCodec {
-
- private final DeduplicatingFieldInfosFormat deduplicatingFieldInfosFormat;
-
- @SuppressWarnings("this-escape")
- protected DeduplicateFieldInfosCodec(String name, Codec delegate) {
- super(name, delegate);
- this.deduplicatingFieldInfosFormat = new DeduplicatingFieldInfosFormat(super.fieldInfosFormat());
- }
-
- @Override
- public FieldInfosFormat fieldInfosFormat() {
- return deduplicatingFieldInfosFormat;
- }
-
- public Codec delegate() {
- return delegate;
- }
-
- }
}
diff --git a/server/src/main/java/org/elasticsearch/index/codec/DeduplicateFieldInfosCodec.java b/server/src/main/java/org/elasticsearch/index/codec/DeduplicateFieldInfosCodec.java
new file mode 100644
index 0000000000000..43cdcc39235e8
--- /dev/null
+++ b/server/src/main/java/org/elasticsearch/index/codec/DeduplicateFieldInfosCodec.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the "Elastic License
+ * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
+ * Public License v 1"; you may not use this file except in compliance with, at
+ * your election, the "Elastic License 2.0", the "GNU Affero General Public
+ * License v3.0 only", or the "Server Side Public License, v 1".
+ */
+
+package org.elasticsearch.index.codec;
+
+import org.apache.lucene.codecs.Codec;
+import org.apache.lucene.codecs.FieldInfosFormat;
+import org.apache.lucene.codecs.FilterCodec;
+
+public final class DeduplicateFieldInfosCodec extends FilterCodec {
+
+ private final DeduplicatingFieldInfosFormat deduplicatingFieldInfosFormat;
+
+ @SuppressWarnings("this-escape")
+ protected DeduplicateFieldInfosCodec(String name, Codec delegate) {
+ super(name, delegate);
+ this.deduplicatingFieldInfosFormat = new DeduplicatingFieldInfosFormat(super.fieldInfosFormat());
+ }
+
+ @Override
+ public FieldInfosFormat fieldInfosFormat() {
+ return deduplicatingFieldInfosFormat;
+ }
+
+ public Codec delegate() {
+ return delegate;
+ }
+
+}
diff --git a/server/src/test/java/org/elasticsearch/index/mapper/CompletionFieldMapperTests.java b/server/src/test/java/org/elasticsearch/index/mapper/CompletionFieldMapperTests.java
index 079521b26b666..e15c9731366a8 100644
--- a/server/src/test/java/org/elasticsearch/index/mapper/CompletionFieldMapperTests.java
+++ b/server/src/test/java/org/elasticsearch/index/mapper/CompletionFieldMapperTests.java
@@ -40,6 +40,7 @@
import org.elasticsearch.index.analysis.IndexAnalyzers;
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.codec.CodecService;
+import org.elasticsearch.index.codec.DeduplicateFieldInfosCodec;
import org.elasticsearch.index.codec.LegacyPerFieldMapperCodec;
import org.elasticsearch.index.codec.PerFieldMapperCodec;
import org.elasticsearch.xcontent.ToXContent;
@@ -157,7 +158,7 @@ public void testPostingsFormat() throws IOException {
assertThat(codec, instanceOf(PerFieldMapperCodec.class));
assertThat(((PerFieldMapperCodec) codec).getPostingsFormatForField("field"), instanceOf(latestLuceneCPClass));
} else {
- if (codec instanceof CodecService.DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
+ if (codec instanceof DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
codec = deduplicateFieldInfosCodec.delegate();
}
assertThat(codec, instanceOf(LegacyPerFieldMapperCodec.class));
diff --git a/server/src/test/java/org/elasticsearch/index/mapper/vectors/DenseVectorFieldMapperTests.java b/server/src/test/java/org/elasticsearch/index/mapper/vectors/DenseVectorFieldMapperTests.java
index 0b58986091f1d..a90084bd4b17c 100644
--- a/server/src/test/java/org/elasticsearch/index/mapper/vectors/DenseVectorFieldMapperTests.java
+++ b/server/src/test/java/org/elasticsearch/index/mapper/vectors/DenseVectorFieldMapperTests.java
@@ -30,6 +30,7 @@
import org.elasticsearch.index.IndexVersion;
import org.elasticsearch.index.IndexVersions;
import org.elasticsearch.index.codec.CodecService;
+import org.elasticsearch.index.codec.DeduplicateFieldInfosCodec;
import org.elasticsearch.index.codec.LegacyPerFieldMapperCodec;
import org.elasticsearch.index.codec.PerFieldMapperCodec;
import org.elasticsearch.index.codec.vectors.BFloat16;
@@ -1923,7 +1924,7 @@ public void testKnnVectorsFormat() throws IOException {
assertThat(codec, instanceOf(PerFieldMapperCodec.class));
knnVectorsFormat = ((PerFieldMapperCodec) codec).getKnnVectorsFormatForField("field");
} else {
- if (codec instanceof CodecService.DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
+ if (codec instanceof DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
codec = deduplicateFieldInfosCodec.delegate();
}
assertThat(codec, instanceOf(LegacyPerFieldMapperCodec.class));
@@ -1968,7 +1969,7 @@ public void testKnnQuantizedFlatVectorsFormat() throws IOException {
assertThat(codec, instanceOf(PerFieldMapperCodec.class));
knnVectorsFormat = ((PerFieldMapperCodec) codec).getKnnVectorsFormatForField("field");
} else {
- if (codec instanceof CodecService.DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
+ if (codec instanceof DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
codec = deduplicateFieldInfosCodec.delegate();
}
assertThat(codec, instanceOf(LegacyPerFieldMapperCodec.class));
@@ -2019,7 +2020,7 @@ public void testKnnQuantizedHNSWVectorsFormat() throws IOException {
assertThat(codec, instanceOf(PerFieldMapperCodec.class));
knnVectorsFormat = ((PerFieldMapperCodec) codec).getKnnVectorsFormatForField("field");
} else {
- if (codec instanceof CodecService.DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
+ if (codec instanceof DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
codec = deduplicateFieldInfosCodec.delegate();
}
assertThat(codec, instanceOf(LegacyPerFieldMapperCodec.class));
@@ -2065,7 +2066,7 @@ public void testKnnBBQHNSWVectorsFormat() throws IOException {
assertThat(codec, instanceOf(PerFieldMapperCodec.class));
knnVectorsFormat = ((PerFieldMapperCodec) codec).getKnnVectorsFormatForField("field");
} else {
- if (codec instanceof CodecService.DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
+ if (codec instanceof DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
codec = deduplicateFieldInfosCodec.delegate();
}
assertThat(codec, instanceOf(LegacyPerFieldMapperCodec.class));
@@ -2108,7 +2109,7 @@ public void testKnnBBQIVFVectorsFormat() throws IOException {
assertThat(codec, instanceOf(PerFieldMapperCodec.class));
knnVectorsFormat = ((PerFieldMapperCodec) codec).getKnnVectorsFormatForField("field");
} else {
- if (codec instanceof CodecService.DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
+ if (codec instanceof DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
codec = deduplicateFieldInfosCodec.delegate();
}
assertThat(codec, instanceOf(LegacyPerFieldMapperCodec.class));
@@ -2160,7 +2161,7 @@ public void testKnnHalfByteQuantizedHNSWVectorsFormat() throws IOException {
assertThat(codec, instanceOf(PerFieldMapperCodec.class));
knnVectorsFormat = ((PerFieldMapperCodec) codec).getKnnVectorsFormatForField("field");
} else {
- if (codec instanceof CodecService.DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
+ if (codec instanceof DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
codec = deduplicateFieldInfosCodec.delegate();
}
assertThat(codec, instanceOf(LegacyPerFieldMapperCodec.class));
diff --git a/x-pack/plugin/gpu/src/test/java/org/elasticsearch/xpack/gpu/codec/GPUDenseVectorFieldMapperTests.java b/x-pack/plugin/gpu/src/test/java/org/elasticsearch/xpack/gpu/codec/GPUDenseVectorFieldMapperTests.java
index 3f235ac37458f..19a42d90563a4 100644
--- a/x-pack/plugin/gpu/src/test/java/org/elasticsearch/xpack/gpu/codec/GPUDenseVectorFieldMapperTests.java
+++ b/x-pack/plugin/gpu/src/test/java/org/elasticsearch/xpack/gpu/codec/GPUDenseVectorFieldMapperTests.java
@@ -11,6 +11,7 @@
import org.apache.lucene.codecs.KnnVectorsFormat;
import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.index.codec.CodecService;
+import org.elasticsearch.index.codec.DeduplicateFieldInfosCodec;
import org.elasticsearch.index.codec.LegacyPerFieldMapperCodec;
import org.elasticsearch.index.codec.PerFieldMapperCodec;
import org.elasticsearch.index.mapper.MapperService;
@@ -74,7 +75,7 @@ private KnnVectorsFormat getKnnVectorsFormat(String indexOptionsType) throws IOE
assertThat(codec, instanceOf(PerFieldMapperCodec.class));
return ((PerFieldMapperCodec) codec).getKnnVectorsFormatForField("field");
} else {
- if (codec instanceof CodecService.DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
+ if (codec instanceof DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
codec = deduplicateFieldInfosCodec.delegate();
}
assertThat(codec, instanceOf(LegacyPerFieldMapperCodec.class));
From 8c1f45e44c1f913c10e995bf796832d384a98d91 Mon Sep 17 00:00:00 2001
From: Anton Persson
Date: Wed, 12 Nov 2025 15:27:58 +0100
Subject: [PATCH 3/8] Single loop for FieldInfo processing
Previously both DeduplicatingFieldInfosFormat and
TSDBSyntheticIdCodec.RewriteFieldInfosFormat would iterate over
FieldInfos.
This is now optimised by letting
TSDBSyntheticIdCodec.RewriteFieldInfosFormat extend
DeduplicatingFieldInfosFormat in order to let RewriteFieldInfosFormat
utilise the iteration done by DeduplicatingFieldInfosFormat.
Also let TSDBSyntheticIdCodec extend DeduplicateFieldInfosCodec so that
we can simplify the codec wrapping to always use only one of them.
---
.../index/codec/CodecService.java | 8 +-
.../codec/DeduplicateFieldInfosCodec.java | 15 ++-
.../codec/DeduplicatingFieldInfosFormat.java | 51 +++++-----
.../codec/tsdb/TSDBSyntheticIdCodec.java | 96 +++++++++----------
4 files changed, 86 insertions(+), 84 deletions(-)
diff --git a/server/src/main/java/org/elasticsearch/index/codec/CodecService.java b/server/src/main/java/org/elasticsearch/index/codec/CodecService.java
index 5b54a25042233..e975c637b919e 100644
--- a/server/src/main/java/org/elasticsearch/index/codec/CodecService.java
+++ b/server/src/main/java/org/elasticsearch/index/codec/CodecService.java
@@ -69,11 +69,9 @@ public CodecService(@Nullable MapperService mapperService, BigArrays bigArrays)
assert useTsdbSyntheticId == false || mapperService.getIndexSettings().getMode() == IndexMode.TIME_SERIES;
this.codecs = codecs.entrySet().stream().collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, e -> {
- Codec codec = new DeduplicateFieldInfosCodec(e.getValue().getName(), e.getValue());
- if (useTsdbSyntheticId && codec instanceof TSDBSyntheticIdCodec == false) {
- codec = new TSDBSyntheticIdCodec(codec.getName(), codec);
- }
- return codec;
+ String name = e.getValue().getName();
+ Codec codec = e.getValue();
+ return useTsdbSyntheticId ? new TSDBSyntheticIdCodec(name, codec) : new DeduplicateFieldInfosCodec(name, codec);
}));
}
diff --git a/server/src/main/java/org/elasticsearch/index/codec/DeduplicateFieldInfosCodec.java b/server/src/main/java/org/elasticsearch/index/codec/DeduplicateFieldInfosCodec.java
index 43cdcc39235e8..18b4aedbeae2f 100644
--- a/server/src/main/java/org/elasticsearch/index/codec/DeduplicateFieldInfosCodec.java
+++ b/server/src/main/java/org/elasticsearch/index/codec/DeduplicateFieldInfosCodec.java
@@ -12,20 +12,25 @@
import org.apache.lucene.codecs.Codec;
import org.apache.lucene.codecs.FieldInfosFormat;
import org.apache.lucene.codecs.FilterCodec;
+import org.elasticsearch.index.codec.tsdb.TSDBSyntheticIdCodec;
-public final class DeduplicateFieldInfosCodec extends FilterCodec {
+public sealed class DeduplicateFieldInfosCodec extends FilterCodec permits TSDBSyntheticIdCodec {
- private final DeduplicatingFieldInfosFormat deduplicatingFieldInfosFormat;
+ private final DeduplicatingFieldInfosFormat fieldInfosFormat;
@SuppressWarnings("this-escape")
protected DeduplicateFieldInfosCodec(String name, Codec delegate) {
super(name, delegate);
- this.deduplicatingFieldInfosFormat = new DeduplicatingFieldInfosFormat(super.fieldInfosFormat());
+ this.fieldInfosFormat = createFieldInfosFormat(delegate.fieldInfosFormat());
+ }
+
+ protected DeduplicatingFieldInfosFormat createFieldInfosFormat(FieldInfosFormat delegate) {
+ return new DeduplicatingFieldInfosFormat(delegate);
}
@Override
- public FieldInfosFormat fieldInfosFormat() {
- return deduplicatingFieldInfosFormat;
+ public final FieldInfosFormat fieldInfosFormat() {
+ return fieldInfosFormat;
}
public Codec delegate() {
diff --git a/server/src/main/java/org/elasticsearch/index/codec/DeduplicatingFieldInfosFormat.java b/server/src/main/java/org/elasticsearch/index/codec/DeduplicatingFieldInfosFormat.java
index 00614140e237a..86a2703159e65 100644
--- a/server/src/main/java/org/elasticsearch/index/codec/DeduplicatingFieldInfosFormat.java
+++ b/server/src/main/java/org/elasticsearch/index/codec/DeduplicatingFieldInfosFormat.java
@@ -18,6 +18,7 @@
import org.elasticsearch.common.util.Maps;
import org.elasticsearch.common.util.StringLiteralDeduplicator;
import org.elasticsearch.common.util.concurrent.ConcurrentCollections;
+import org.elasticsearch.index.codec.tsdb.TSDBSyntheticIdCodec;
import org.elasticsearch.index.mapper.FieldMapper;
import java.io.IOException;
@@ -28,7 +29,7 @@
* cases attribute maps on read. We use this to reduce the per-field overhead for Elasticsearch instances holding a large number of
* segments.
*/
-public final class DeduplicatingFieldInfosFormat extends FieldInfosFormat {
+public sealed class DeduplicatingFieldInfosFormat extends FieldInfosFormat permits TSDBSyntheticIdCodec.RewriteFieldInfosFormat {
private static final Map
*/
-public class TSDBSyntheticIdCodec extends FilterCodec {
-
- private final RewriteFieldInfosFormat fieldInfosFormat;
+public final class TSDBSyntheticIdCodec extends DeduplicateFieldInfosCodec {
private final EnsureNoPostingsFormat postingsFormat;
public TSDBSyntheticIdCodec(String name, Codec delegate) {
super(name, delegate);
- this.fieldInfosFormat = new RewriteFieldInfosFormat(delegate.fieldInfosFormat());
this.postingsFormat = new EnsureNoPostingsFormat(delegate.postingsFormat());
}
@Override
- public final FieldInfosFormat fieldInfosFormat() {
- return fieldInfosFormat;
+ protected DeduplicatingFieldInfosFormat createFieldInfosFormat(FieldInfosFormat delegate) {
+ return new RewriteFieldInfosFormat(delegate);
}
@Override
@@ -77,12 +75,10 @@ public PostingsFormat postingsFormat() {
/**
* {@link FieldInfosFormat} that overwrites the {@link FieldInfos}.
*/
- private static class RewriteFieldInfosFormat extends FieldInfosFormat {
-
- private final FieldInfosFormat delegate;
+ public static final class RewriteFieldInfosFormat extends DeduplicatingFieldInfosFormat {
- private RewriteFieldInfosFormat(FieldInfosFormat delegate) {
- this.delegate = delegate;
+ RewriteFieldInfosFormat(FieldInfosFormat delegate) {
+ super(delegate);
}
private void ensureSyntheticIdFields(FieldInfos fieldInfos) {
@@ -126,7 +122,6 @@ private void ensureSyntheticIdFields(FieldInfos fieldInfos) {
@Override
public void write(Directory directory, SegmentInfo segmentInfo, String segmentSuffix, FieldInfos fieldInfos, IOContext context)
throws IOException {
-
// Change the _id field index options from IndexOptions.DOCS to IndexOptions.NONE
final var infos = new FieldInfo[fieldInfos.size()];
int i = 0;
@@ -170,56 +165,53 @@ public void write(Directory directory, SegmentInfo segmentInfo, String segmentSu
fieldInfos = new FieldInfos(infos);
ensureSyntheticIdFields(fieldInfos);
- delegate.write(directory, segmentInfo, segmentSuffix, fieldInfos, context);
+ super.write(directory, segmentInfo, segmentSuffix, fieldInfos, context);
}
@Override
- public FieldInfos read(Directory directory, SegmentInfo segmentInfo, String segmentSuffix, IOContext iocontext) throws IOException {
- final var fieldInfos = delegate.read(directory, segmentInfo, segmentSuffix, iocontext);
+ protected void validateFieldInfos(FieldInfos fieldInfos) {
ensureSyntheticIdFields(fieldInfos);
+ }
+ @Override
+ protected FieldInfo processFieldInfo(FieldInfo fi) {
// Change the _id field index options from IndexOptions.NONE to IndexOptions.DOCS, so that terms and postings work when
// applying doc values updates in Lucene.
- final var infos = new FieldInfo[fieldInfos.size()];
- int i = 0;
- for (FieldInfo fi : fieldInfos) {
- if (SYNTHETIC_ID.equals(fi.getName())) {
- final var attributes = new HashMap<>(fi.attributes());
+ if (SYNTHETIC_ID.equals(fi.getName())) {
+ final var attributes = new HashMap<>(fi.attributes());
- // Assert that PerFieldPostingsFormat are not written to field infos on disk
- assert attributes.containsKey(PerFieldPostingsFormat.PER_FIELD_FORMAT_KEY) == false;
- assert attributes.containsKey(PerFieldPostingsFormat.PER_FIELD_SUFFIX_KEY) == false;
+ // Assert that PerFieldPostingsFormat are not written to field infos on disk
+ assert attributes.containsKey(PerFieldPostingsFormat.PER_FIELD_FORMAT_KEY) == false;
+ assert attributes.containsKey(PerFieldPostingsFormat.PER_FIELD_SUFFIX_KEY) == false;
- // Inject attributes so that PerFieldPostingsFormat maps the synthetic _id field to the TSDBSyntheticIdPostingsFormat
- // This would normally be handled transparently by PerFieldPostingsFormat, but such attributes are only added if terms
- // are produced during indexing, which is not the case for the synthetic _id field.
- attributes.put(PerFieldPostingsFormat.PER_FIELD_FORMAT_KEY, TSDBSyntheticIdPostingsFormat.FORMAT_NAME);
- attributes.put(PerFieldPostingsFormat.PER_FIELD_SUFFIX_KEY, TSDBSyntheticIdPostingsFormat.SUFFIX);
+ // Inject attributes so that PerFieldPostingsFormat maps the synthetic _id field to the TSDBSyntheticIdPostingsFormat
+ // This would normally be handled transparently by PerFieldPostingsFormat, but such attributes are only added if terms
+ // are produced during indexing, which is not the case for the synthetic _id field.
+ attributes.put(PerFieldPostingsFormat.PER_FIELD_FORMAT_KEY, TSDBSyntheticIdPostingsFormat.FORMAT_NAME);
+ attributes.put(PerFieldPostingsFormat.PER_FIELD_SUFFIX_KEY, TSDBSyntheticIdPostingsFormat.SUFFIX);
- fi = new FieldInfo(
- fi.getName(),
- fi.getFieldNumber(),
- fi.hasTermVectors(),
- true,
- fi.hasPayloads(),
- IndexOptions.DOCS,
- fi.getDocValuesType(),
- fi.docValuesSkipIndexType(),
- fi.getDocValuesGen(),
- attributes,
- fi.getPointDimensionCount(),
- fi.getPointIndexDimensionCount(),
- fi.getPointNumBytes(),
- fi.getVectorDimension(),
- fi.getVectorEncoding(),
- fi.getVectorSimilarityFunction(),
- fi.isSoftDeletesField(),
- fi.isParentField()
- );
- }
- infos[i++] = fi;
+ fi = new FieldInfo(
+ fi.getName(),
+ fi.getFieldNumber(),
+ fi.hasTermVectors(),
+ true,
+ fi.hasPayloads(),
+ IndexOptions.DOCS,
+ fi.getDocValuesType(),
+ fi.docValuesSkipIndexType(),
+ fi.getDocValuesGen(),
+ attributes,
+ fi.getPointDimensionCount(),
+ fi.getPointIndexDimensionCount(),
+ fi.getPointNumBytes(),
+ fi.getVectorDimension(),
+ fi.getVectorEncoding(),
+ fi.getVectorSimilarityFunction(),
+ fi.isSoftDeletesField(),
+ fi.isParentField()
+ );
}
- return new FieldInfos(infos);
+ return super.processFieldInfo(fi);
}
}
From 21e6faff7a1a4cb2d011538c9ad03b85c16cbcaf Mon Sep 17 00:00:00 2001
From: Anton Persson
Date: Wed, 12 Nov 2025 15:41:22 +0100
Subject: [PATCH 4/8] Update docs/changelog/137967.yaml
---
docs/changelog/137967.yaml | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 docs/changelog/137967.yaml
diff --git a/docs/changelog/137967.yaml b/docs/changelog/137967.yaml
new file mode 100644
index 0000000000000..11c45b7cc86da
--- /dev/null
+++ b/docs/changelog/137967.yaml
@@ -0,0 +1,5 @@
+pr: 137967
+summary: Single loop for `FielfInfo` processing
+area: TSDB
+type: enhancement
+issues: []
From cb9fdb711098919f34faa1da0619e2773412ece7 Mon Sep 17 00:00:00 2001
From: Anton Persson
Date: Wed, 12 Nov 2025 16:53:22 +0100
Subject: [PATCH 5/8] Fix test failures expecting inheritance
---
.../mapper/CompletionFieldMapperTests.java | 6 +--
.../vectors/DenseVectorFieldMapperTests.java | 38 +++++++------------
.../codec/GPUDenseVectorFieldMapperTests.java | 6 +--
3 files changed, 20 insertions(+), 30 deletions(-)
diff --git a/server/src/test/java/org/elasticsearch/index/mapper/CompletionFieldMapperTests.java b/server/src/test/java/org/elasticsearch/index/mapper/CompletionFieldMapperTests.java
index e15c9731366a8..b90d457b268f9 100644
--- a/server/src/test/java/org/elasticsearch/index/mapper/CompletionFieldMapperTests.java
+++ b/server/src/test/java/org/elasticsearch/index/mapper/CompletionFieldMapperTests.java
@@ -154,13 +154,13 @@ public void testPostingsFormat() throws IOException {
MapperService mapperService = createMapperService(fieldMapping(this::minimalMapping));
CodecService codecService = new CodecService(mapperService, BigArrays.NON_RECYCLING_INSTANCE);
Codec codec = codecService.codec("default");
+ if (codec instanceof DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
+ codec = deduplicateFieldInfosCodec.delegate();
+ }
if (CodecService.ZSTD_STORED_FIELDS_FEATURE_FLAG) {
assertThat(codec, instanceOf(PerFieldMapperCodec.class));
assertThat(((PerFieldMapperCodec) codec).getPostingsFormatForField("field"), instanceOf(latestLuceneCPClass));
} else {
- if (codec instanceof DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
- codec = deduplicateFieldInfosCodec.delegate();
- }
assertThat(codec, instanceOf(LegacyPerFieldMapperCodec.class));
assertThat(((LegacyPerFieldMapperCodec) codec).getPostingsFormatForField("field"), instanceOf(latestLuceneCPClass));
}
diff --git a/server/src/test/java/org/elasticsearch/index/mapper/vectors/DenseVectorFieldMapperTests.java b/server/src/test/java/org/elasticsearch/index/mapper/vectors/DenseVectorFieldMapperTests.java
index a90084bd4b17c..e8e59045ed541 100644
--- a/server/src/test/java/org/elasticsearch/index/mapper/vectors/DenseVectorFieldMapperTests.java
+++ b/server/src/test/java/org/elasticsearch/index/mapper/vectors/DenseVectorFieldMapperTests.java
@@ -1918,15 +1918,12 @@ public void testKnnVectorsFormat() throws IOException {
b.endObject();
}));
CodecService codecService = new CodecService(mapperService, BigArrays.NON_RECYCLING_INSTANCE);
- Codec codec = codecService.codec("default");
+ Codec codec = getUnwrappedCodec(codecService);
KnnVectorsFormat knnVectorsFormat;
if (CodecService.ZSTD_STORED_FIELDS_FEATURE_FLAG) {
assertThat(codec, instanceOf(PerFieldMapperCodec.class));
knnVectorsFormat = ((PerFieldMapperCodec) codec).getKnnVectorsFormatForField("field");
} else {
- if (codec instanceof DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
- codec = deduplicateFieldInfosCodec.delegate();
- }
assertThat(codec, instanceOf(LegacyPerFieldMapperCodec.class));
knnVectorsFormat = ((LegacyPerFieldMapperCodec) codec).getKnnVectorsFormatForField("field");
}
@@ -1963,15 +1960,12 @@ public void testKnnQuantizedFlatVectorsFormat() throws IOException {
b.endObject();
}));
CodecService codecService = new CodecService(mapperService, BigArrays.NON_RECYCLING_INSTANCE);
- Codec codec = codecService.codec("default");
+ Codec codec = getUnwrappedCodec(codecService);
KnnVectorsFormat knnVectorsFormat;
if (CodecService.ZSTD_STORED_FIELDS_FEATURE_FLAG) {
assertThat(codec, instanceOf(PerFieldMapperCodec.class));
knnVectorsFormat = ((PerFieldMapperCodec) codec).getKnnVectorsFormatForField("field");
} else {
- if (codec instanceof DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
- codec = deduplicateFieldInfosCodec.delegate();
- }
assertThat(codec, instanceOf(LegacyPerFieldMapperCodec.class));
knnVectorsFormat = ((LegacyPerFieldMapperCodec) codec).getKnnVectorsFormatForField("field");
}
@@ -2014,15 +2008,12 @@ public void testKnnQuantizedHNSWVectorsFormat() throws IOException {
b.endObject();
}));
CodecService codecService = new CodecService(mapperService, BigArrays.NON_RECYCLING_INSTANCE);
- Codec codec = codecService.codec("default");
+ Codec codec = getUnwrappedCodec(codecService);
KnnVectorsFormat knnVectorsFormat;
if (CodecService.ZSTD_STORED_FIELDS_FEATURE_FLAG) {
assertThat(codec, instanceOf(PerFieldMapperCodec.class));
knnVectorsFormat = ((PerFieldMapperCodec) codec).getKnnVectorsFormatForField("field");
} else {
- if (codec instanceof DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
- codec = deduplicateFieldInfosCodec.delegate();
- }
assertThat(codec, instanceOf(LegacyPerFieldMapperCodec.class));
knnVectorsFormat = ((LegacyPerFieldMapperCodec) codec).getKnnVectorsFormatForField("field");
}
@@ -2060,15 +2051,12 @@ public void testKnnBBQHNSWVectorsFormat() throws IOException {
b.endObject();
}));
CodecService codecService = new CodecService(mapperService, BigArrays.NON_RECYCLING_INSTANCE);
- Codec codec = codecService.codec("default");
+ Codec codec = getUnwrappedCodec(codecService);
KnnVectorsFormat knnVectorsFormat;
if (CodecService.ZSTD_STORED_FIELDS_FEATURE_FLAG) {
assertThat(codec, instanceOf(PerFieldMapperCodec.class));
knnVectorsFormat = ((PerFieldMapperCodec) codec).getKnnVectorsFormatForField("field");
} else {
- if (codec instanceof DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
- codec = deduplicateFieldInfosCodec.delegate();
- }
assertThat(codec, instanceOf(LegacyPerFieldMapperCodec.class));
knnVectorsFormat = ((LegacyPerFieldMapperCodec) codec).getKnnVectorsFormatForField("field");
}
@@ -2103,15 +2091,12 @@ public void testKnnBBQIVFVectorsFormat() throws IOException {
b.endObject();
}));
CodecService codecService = new CodecService(mapperService, BigArrays.NON_RECYCLING_INSTANCE);
- Codec codec = codecService.codec("default");
+ Codec codec = getUnwrappedCodec(codecService);
KnnVectorsFormat knnVectorsFormat;
if (CodecService.ZSTD_STORED_FIELDS_FEATURE_FLAG) {
assertThat(codec, instanceOf(PerFieldMapperCodec.class));
knnVectorsFormat = ((PerFieldMapperCodec) codec).getKnnVectorsFormatForField("field");
} else {
- if (codec instanceof DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
- codec = deduplicateFieldInfosCodec.delegate();
- }
assertThat(codec, instanceOf(LegacyPerFieldMapperCodec.class));
knnVectorsFormat = ((LegacyPerFieldMapperCodec) codec).getKnnVectorsFormatForField("field");
}
@@ -2155,15 +2140,12 @@ public void testKnnHalfByteQuantizedHNSWVectorsFormat() throws IOException {
b.endObject();
}));
CodecService codecService = new CodecService(mapperService, BigArrays.NON_RECYCLING_INSTANCE);
- Codec codec = codecService.codec("default");
+ Codec codec = getUnwrappedCodec(codecService);
KnnVectorsFormat knnVectorsFormat;
if (CodecService.ZSTD_STORED_FIELDS_FEATURE_FLAG) {
assertThat(codec, instanceOf(PerFieldMapperCodec.class));
knnVectorsFormat = ((PerFieldMapperCodec) codec).getKnnVectorsFormatForField("field");
} else {
- if (codec instanceof DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
- codec = deduplicateFieldInfosCodec.delegate();
- }
assertThat(codec, instanceOf(LegacyPerFieldMapperCodec.class));
knnVectorsFormat = ((LegacyPerFieldMapperCodec) codec).getKnnVectorsFormatForField("field");
}
@@ -2201,6 +2183,14 @@ public void testInvalidVectorDimensions() {
}
}
+ private static Codec getUnwrappedCodec(CodecService codecService) {
+ Codec codec = codecService.codec("default");
+ if (codec instanceof DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
+ codec = deduplicateFieldInfosCodec.delegate();
+ }
+ return codec;
+ }
+
@Override
protected IngestScriptSupport ingestScriptSupport() {
throw new AssumptionViolatedException("not supported");
diff --git a/x-pack/plugin/gpu/src/test/java/org/elasticsearch/xpack/gpu/codec/GPUDenseVectorFieldMapperTests.java b/x-pack/plugin/gpu/src/test/java/org/elasticsearch/xpack/gpu/codec/GPUDenseVectorFieldMapperTests.java
index 19a42d90563a4..91b0f7fda64e2 100644
--- a/x-pack/plugin/gpu/src/test/java/org/elasticsearch/xpack/gpu/codec/GPUDenseVectorFieldMapperTests.java
+++ b/x-pack/plugin/gpu/src/test/java/org/elasticsearch/xpack/gpu/codec/GPUDenseVectorFieldMapperTests.java
@@ -71,13 +71,13 @@ private KnnVectorsFormat getKnnVectorsFormat(String indexOptionsType) throws IOE
}));
CodecService codecService = new CodecService(mapperService, BigArrays.NON_RECYCLING_INSTANCE);
Codec codec = codecService.codec("default");
+ if (codec instanceof DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
+ codec = deduplicateFieldInfosCodec.delegate();
+ }
if (CodecService.ZSTD_STORED_FIELDS_FEATURE_FLAG) {
assertThat(codec, instanceOf(PerFieldMapperCodec.class));
return ((PerFieldMapperCodec) codec).getKnnVectorsFormatForField("field");
} else {
- if (codec instanceof DeduplicateFieldInfosCodec deduplicateFieldInfosCodec) {
- codec = deduplicateFieldInfosCodec.delegate();
- }
assertThat(codec, instanceOf(LegacyPerFieldMapperCodec.class));
return ((LegacyPerFieldMapperCodec) codec).getKnnVectorsFormatForField("field");
}
From 57da3f72cd57a25721421247fdbbb3323c40cbf4 Mon Sep 17 00:00:00 2001
From: Anton Persson
Date: Thu, 13 Nov 2025 08:49:13 +0100
Subject: [PATCH 6/8] Fix more test failures expecting inheritance
---
.../elasticsearch/index/codec/CodecTests.java | 21 ++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/server/src/test/java/org/elasticsearch/index/codec/CodecTests.java b/server/src/test/java/org/elasticsearch/index/codec/CodecTests.java
index 331d84d9e4f61..8d1d4feda9038 100644
--- a/server/src/test/java/org/elasticsearch/index/codec/CodecTests.java
+++ b/server/src/test/java/org/elasticsearch/index/codec/CodecTests.java
@@ -49,13 +49,13 @@ public class CodecTests extends ESTestCase {
public void testResolveDefaultCodecs() throws Exception {
assumeTrue("Only when zstd_stored_fields feature flag is enabled", CodecService.ZSTD_STORED_FIELDS_FEATURE_FLAG);
CodecService codecService = createCodecService();
- assertThat(codecService.codec("default"), instanceOf(PerFieldMapperCodec.class));
- assertThat(codecService.codec("default"), instanceOf(Elasticsearch92Lucene103Codec.class));
+ assertThat(unwrappedCodec(codecService, "default"), instanceOf(PerFieldMapperCodec.class));
+ assertThat(unwrappedCodec(codecService, "default"), instanceOf(Elasticsearch92Lucene103Codec.class));
}
public void testDefault() throws Exception {
assumeTrue("Only when zstd_stored_fields feature flag is enabled", CodecService.ZSTD_STORED_FIELDS_FEATURE_FLAG);
- Codec codec = createCodecService().codec("default");
+ Codec codec = unwrappedCodec(createCodecService(), "default");
assertEquals(
"Zstd814StoredFieldsFormat(compressionMode=ZSTD(level=1), chunkSize=14336, maxDocsPerChunk=128, blockShift=10)",
codec.storedFieldsFormat().toString()
@@ -63,7 +63,7 @@ public void testDefault() throws Exception {
}
public void testBestCompression() throws Exception {
- Codec codec = createCodecService().codec("best_compression");
+ Codec codec = unwrappedCodec(createCodecService(), "best_compression");
assertEquals(
"Zstd814StoredFieldsFormat(compressionMode=ZSTD(level=3), chunkSize=245760, maxDocsPerChunk=2048, blockShift=10)",
codec.storedFieldsFormat().toString()
@@ -71,7 +71,7 @@ public void testBestCompression() throws Exception {
}
public void testLegacyDefault() throws Exception {
- Codec codec = createCodecService().codec("legacy_default");
+ Codec codec = unwrappedCodec(createCodecService(), "legacy_default");
assertThat(codec.storedFieldsFormat(), Matchers.instanceOf(Lucene90StoredFieldsFormat.class));
// Make sure the legacy codec is writable
try (Directory dir = newDirectory(); IndexWriter w = new IndexWriter(dir, newIndexWriterConfig().setCodec(codec))) {
@@ -84,7 +84,7 @@ public void testLegacyDefault() throws Exception {
}
public void testLegacyBestCompression() throws Exception {
- Codec codec = createCodecService().codec("legacy_best_compression");
+ Codec codec = unwrappedCodec(createCodecService(), "legacy_best_compression");
assertThat(codec.storedFieldsFormat(), Matchers.instanceOf(Lucene90StoredFieldsFormat.class));
// Make sure the legacy codec is writable
try (Directory dir = newDirectory(); IndexWriter w = new IndexWriter(dir, newIndexWriterConfig().setCodec(codec))) {
@@ -98,7 +98,7 @@ public void testLegacyBestCompression() throws Exception {
public void testCodecRetrievalForUnknownCodec() throws Exception {
CodecService codecService = createCodecService();
- IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> codecService.codec("unknown_codec"));
+ IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> unwrappedCodec(codecService, "unknown_codec"));
assertEquals("failed to find codec [unknown_codec]", exception.getMessage());
}
@@ -148,4 +148,11 @@ private CodecService createCodecService() throws IOException {
return new CodecService(service, BigArrays.NON_RECYCLING_INSTANCE);
}
+ private static Codec unwrappedCodec(CodecService codecService, String codecName) {
+ Codec codec = codecService.codec(codecName);
+ if (codec instanceof DeduplicateFieldInfosCodec deduplicatingCodec) {
+ return deduplicatingCodec.delegate();
+ }
+ return codec;
+ }
}
From bf7579240eeba61df0367f4fc9ae48a826263701 Mon Sep 17 00:00:00 2001
From: elasticsearchmachine
Date: Thu, 13 Nov 2025 07:57:42 +0000
Subject: [PATCH 7/8] [CI] Auto commit changes from spotless
---
.../test/java/org/elasticsearch/index/codec/CodecTests.java | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/server/src/test/java/org/elasticsearch/index/codec/CodecTests.java b/server/src/test/java/org/elasticsearch/index/codec/CodecTests.java
index 8d1d4feda9038..95ae90732aa1a 100644
--- a/server/src/test/java/org/elasticsearch/index/codec/CodecTests.java
+++ b/server/src/test/java/org/elasticsearch/index/codec/CodecTests.java
@@ -98,7 +98,10 @@ public void testLegacyBestCompression() throws Exception {
public void testCodecRetrievalForUnknownCodec() throws Exception {
CodecService codecService = createCodecService();
- IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> unwrappedCodec(codecService, "unknown_codec"));
+ IllegalArgumentException exception = assertThrows(
+ IllegalArgumentException.class,
+ () -> unwrappedCodec(codecService, "unknown_codec")
+ );
assertEquals("failed to find codec [unknown_codec]", exception.getMessage());
}
From 8f212946f1c26c82a2ba07a653f9a14de8902c41 Mon Sep 17 00:00:00 2001
From: Anton Persson
Date: Thu, 13 Nov 2025 14:51:44 +0100
Subject: [PATCH 8/8] Address PR comments
---
.../java/org/elasticsearch/index/codec/CodecService.java | 2 +-
.../index/codec/DeduplicateFieldInfosCodec.java | 4 ++--
.../index/codec/DeduplicatingFieldInfosFormat.java | 4 ++--
.../index/codec/tsdb/TSDBSyntheticIdCodec.java | 8 ++++----
4 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/server/src/main/java/org/elasticsearch/index/codec/CodecService.java b/server/src/main/java/org/elasticsearch/index/codec/CodecService.java
index e975c637b919e..8f2ab54877360 100644
--- a/server/src/main/java/org/elasticsearch/index/codec/CodecService.java
+++ b/server/src/main/java/org/elasticsearch/index/codec/CodecService.java
@@ -71,7 +71,7 @@ public CodecService(@Nullable MapperService mapperService, BigArrays bigArrays)
this.codecs = codecs.entrySet().stream().collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, e -> {
String name = e.getValue().getName();
Codec codec = e.getValue();
- return useTsdbSyntheticId ? new TSDBSyntheticIdCodec(name, codec) : new DeduplicateFieldInfosCodec(name, codec);
+ return useTsdbSyntheticId ? new TSDBSyntheticIdCodec(codec) : new DeduplicateFieldInfosCodec(codec);
}));
}
diff --git a/server/src/main/java/org/elasticsearch/index/codec/DeduplicateFieldInfosCodec.java b/server/src/main/java/org/elasticsearch/index/codec/DeduplicateFieldInfosCodec.java
index 18b4aedbeae2f..83dadc5714e33 100644
--- a/server/src/main/java/org/elasticsearch/index/codec/DeduplicateFieldInfosCodec.java
+++ b/server/src/main/java/org/elasticsearch/index/codec/DeduplicateFieldInfosCodec.java
@@ -19,8 +19,8 @@ public sealed class DeduplicateFieldInfosCodec extends FilterCodec permits TSDBS
private final DeduplicatingFieldInfosFormat fieldInfosFormat;
@SuppressWarnings("this-escape")
- protected DeduplicateFieldInfosCodec(String name, Codec delegate) {
- super(name, delegate);
+ protected DeduplicateFieldInfosCodec(Codec delegate) {
+ super(delegate.getName(), delegate);
this.fieldInfosFormat = createFieldInfosFormat(delegate.fieldInfosFormat());
}
diff --git a/server/src/main/java/org/elasticsearch/index/codec/DeduplicatingFieldInfosFormat.java b/server/src/main/java/org/elasticsearch/index/codec/DeduplicatingFieldInfosFormat.java
index 86a2703159e65..8aee7ca24decb 100644
--- a/server/src/main/java/org/elasticsearch/index/codec/DeduplicatingFieldInfosFormat.java
+++ b/server/src/main/java/org/elasticsearch/index/codec/DeduplicatingFieldInfosFormat.java
@@ -48,14 +48,14 @@ public FieldInfos read(Directory directory, SegmentInfo segmentInfo, String segm
final FieldInfo[] deduplicated = new FieldInfo[fieldInfos.size()];
int i = 0;
for (FieldInfo fi : fieldInfos) {
- deduplicated[i++] = processFieldInfo(fi);
+ deduplicated[i++] = wrapFieldInfo(fi);
}
return new FieldInfosWithUsages(deduplicated);
}
protected void validateFieldInfos(FieldInfos fieldInfos) {}
- protected FieldInfo processFieldInfo(FieldInfo fi) {
+ protected FieldInfo wrapFieldInfo(FieldInfo fi) {
return new FieldInfo(
FieldMapper.internFieldName(fi.getName()),
fi.number,
diff --git a/server/src/main/java/org/elasticsearch/index/codec/tsdb/TSDBSyntheticIdCodec.java b/server/src/main/java/org/elasticsearch/index/codec/tsdb/TSDBSyntheticIdCodec.java
index 9ea9b71794477..236832b50c897 100644
--- a/server/src/main/java/org/elasticsearch/index/codec/tsdb/TSDBSyntheticIdCodec.java
+++ b/server/src/main/java/org/elasticsearch/index/codec/tsdb/TSDBSyntheticIdCodec.java
@@ -57,8 +57,8 @@
public final class TSDBSyntheticIdCodec extends DeduplicateFieldInfosCodec {
private final EnsureNoPostingsFormat postingsFormat;
- public TSDBSyntheticIdCodec(String name, Codec delegate) {
- super(name, delegate);
+ public TSDBSyntheticIdCodec(Codec delegate) {
+ super(delegate);
this.postingsFormat = new EnsureNoPostingsFormat(delegate.postingsFormat());
}
@@ -174,7 +174,7 @@ protected void validateFieldInfos(FieldInfos fieldInfos) {
}
@Override
- protected FieldInfo processFieldInfo(FieldInfo fi) {
+ protected FieldInfo wrapFieldInfo(FieldInfo fi) {
// Change the _id field index options from IndexOptions.NONE to IndexOptions.DOCS, so that terms and postings work when
// applying doc values updates in Lucene.
if (SYNTHETIC_ID.equals(fi.getName())) {
@@ -211,7 +211,7 @@ protected FieldInfo processFieldInfo(FieldInfo fi) {
fi.isParentField()
);
}
- return super.processFieldInfo(fi);
+ return super.wrapFieldInfo(fi);
}
}