Skip to content

Commit 87a2fe6

Browse files
martijnvgnavarone-feekery
authored andcommitted
Handle empty index case in LuceneSyntheticSourceChangesSnapshot (elastic#118996)
In case of synthetic recovery source when the mapping is empty. A test that reproduces failure in elastic#118955 consistently with a potential fix. `MapperService#updateMapping(...)` doesn't set the mapper field if a mapping has no fields, which is what is used in InternalEngine#newChangesSnapshot(...) . This happens when `newMappingMetadata` variable in `MapperService updateMapping(...)` is `null`. Causing an assertion to trip. This change adjusts that assertion to handle an empty index. Closes elastic#118955
1 parent dcd7342 commit 87a2fe6

File tree

5 files changed

+43
-11
lines changed

5 files changed

+43
-11
lines changed

muted-tests.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -288,9 +288,6 @@ tests:
288288
- class: org.elasticsearch.cluster.service.MasterServiceTests
289289
method: testThreadContext
290290
issue: https://github.com/elastic/elasticsearch/issues/118914
291-
- class: org.elasticsearch.smoketest.SmokeTestMultiNodeClientYamlTestSuiteIT
292-
method: test {yaml=indices.create/20_synthetic_source/create index with use_synthetic_source}
293-
issue: https://github.com/elastic/elasticsearch/issues/118955
294291
- class: org.elasticsearch.repositories.blobstore.testkit.analyze.SecureHdfsRepositoryAnalysisRestIT
295292
issue: https://github.com/elastic/elasticsearch/issues/118970
296293
- class: org.elasticsearch.xpack.security.authc.AuthenticationServiceTests

rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/indices.create/20_synthetic_source.yml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2036,14 +2036,12 @@ create index with use_synthetic_source:
20362036
- is_true: test.settings.index.recovery.use_synthetic_source
20372037

20382038
- do:
2039-
bulk:
2039+
index:
20402040
index: test
2041+
id: 1
20412042
refresh: true
2042-
body:
2043-
- '{ "create": { } }'
2044-
- '{ "field": "aaaa" }'
2045-
- '{ "create": { } }'
2046-
- '{ "field": "bbbb" }'
2043+
body: { foo: bar }
2044+
- match: { _version: 1 }
20472045

20482046
- do:
20492047
indices.disk_usage:
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
---
2+
test recovery empty index with use_synthetic_source:
3+
- requires:
4+
cluster_features: ["mapper.synthetic_recovery_source"]
5+
reason: requires synthetic recovery source
6+
7+
- do:
8+
indices.create:
9+
index: test
10+
body:
11+
settings:
12+
index:
13+
number_of_replicas: 0
14+
recovery:
15+
use_synthetic_source: true
16+
mapping:
17+
source:
18+
mode: synthetic
19+
20+
- do:
21+
indices.get_settings: {}
22+
- match: { test.settings.index.mapping.source.mode: synthetic}
23+
- is_true: test.settings.index.recovery.use_synthetic_source
24+
25+
- do:
26+
indices.put_settings:
27+
index: test
28+
body:
29+
index.number_of_replicas: 1
30+
31+
- do:
32+
cluster.health:
33+
wait_for_events: languid

server/src/main/java/org/elasticsearch/index/IndexSettings.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,6 +1049,9 @@ public IndexSettings(final IndexMetadata indexMetadata, final Settings nodeSetti
10491049
recoverySourceEnabled = RecoverySettings.INDICES_RECOVERY_SOURCE_ENABLED_SETTING.get(nodeSettings);
10501050
recoverySourceSyntheticEnabled = scopedSettings.get(RECOVERY_USE_SYNTHETIC_SOURCE_SETTING);
10511051
if (recoverySourceSyntheticEnabled) {
1052+
if (DiscoveryNode.isStateless(settings)) {
1053+
throw new IllegalArgumentException("synthetic recovery source is only allowed in stateful");
1054+
}
10521055
// Verify that all nodes can handle this setting
10531056
if (version.before(IndexVersions.USE_SYNTHETIC_SOURCE_FOR_RECOVERY)
10541057
&& version.between(

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,13 @@ public LuceneSyntheticSourceChangesSnapshot(
7777
IndexVersion indexVersionCreated
7878
) throws IOException {
7979
super(engineSearcher, searchBatchSize, fromSeqNo, toSeqNo, requiredFullRange, accessStats, indexVersionCreated);
80-
assert mappingLookup.isSourceSynthetic();
80+
// a MapperService#updateMapping(...) of empty index may not have been invoked and then mappingLookup is empty
81+
assert engineSearcher.getDirectoryReader().maxDoc() == 0 || mappingLookup.isSourceSynthetic()
82+
: "either an empty index or synthetic source must be enabled for proper functionality.";
8183
// ensure we can buffer at least one document
8284
this.maxMemorySizeInBytes = maxMemorySizeInBytes > 0 ? maxMemorySizeInBytes : 1;
8385
this.sourceLoader = mappingLookup.newSourceLoader(null, SourceFieldMetrics.NOOP);
8486
Set<String> storedFields = sourceLoader.requiredStoredFields();
85-
assert mappingLookup.isSourceSynthetic() : "synthetic source must be enabled for proper functionality.";
8687
this.storedFieldLoader = StoredFieldLoader.create(false, storedFields);
8788
this.lastSeenSeqNo = fromSeqNo - 1;
8889
}

0 commit comments

Comments
 (0)