Skip to content

Commit 63af03a

Browse files
authored
Atomic mapping updates across types (elastic#22220)
This commit makes mapping updates atomic when multiple types in an index are updated. Mappings for an index are now applied in a single atomic operation, which also allows to optimize some of the cross-type updates and checks.
1 parent 1cabf66 commit 63af03a

File tree

17 files changed

+251
-219
lines changed

17 files changed

+251
-219
lines changed

core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataCreateIndexService.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
import org.elasticsearch.index.mapper.DocumentMapper;
6868
import org.elasticsearch.index.mapper.MapperParsingException;
6969
import org.elasticsearch.index.mapper.MapperService;
70+
import org.elasticsearch.index.mapper.MapperService.MergeReason;
7071
import org.elasticsearch.index.query.QueryShardContext;
7172
import org.elasticsearch.indices.IndexCreationException;
7273
import org.elasticsearch.indices.IndicesService;
@@ -356,10 +357,10 @@ public ClusterState execute(ClusterState currentState) throws Exception {
356357
// now add the mappings
357358
MapperService mapperService = indexService.mapperService();
358359
try {
359-
mapperService.merge(mappings, request.updateAllTypes());
360-
} catch (MapperParsingException mpe) {
360+
mapperService.merge(mappings, MergeReason.MAPPING_UPDATE, request.updateAllTypes());
361+
} catch (Exception e) {
361362
removalExtraInfo = "failed on parsing default mapping/mappings on index creation";
362-
throw mpe;
363+
throw e;
363364
}
364365

365366
// the context is only used for validation so it's fine to pass fake values for the shard id and the current

core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesService.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,15 +141,11 @@ ClusterState innerExecute(ClusterState currentState, Iterable<AliasAction> actio
141141
// temporarily create the index and add mappings so we can parse the filter
142142
try {
143143
indexService = indicesService.createIndex(index, emptyList(), shardId -> {});
144+
indicesToClose.add(index.getIndex());
144145
} catch (IOException e) {
145146
throw new ElasticsearchException("Failed to create temporary index for parsing the alias", e);
146147
}
147-
for (ObjectCursor<MappingMetaData> cursor : index.getMappings().values()) {
148-
MappingMetaData mappingMetaData = cursor.value;
149-
indexService.mapperService().merge(mappingMetaData.type(), mappingMetaData.source(),
150-
MapperService.MergeReason.MAPPING_RECOVERY, false);
151-
}
152-
indicesToClose.add(index.getIndex());
148+
indexService.mapperService().merge(index, MapperService.MergeReason.MAPPING_RECOVERY, false);
153149
}
154150
indices.put(action.getIndex(), indexService);
155151
}

core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexTemplateService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.elasticsearch.index.IndexService;
4040
import org.elasticsearch.index.mapper.MapperParsingException;
4141
import org.elasticsearch.index.mapper.MapperService;
42+
import org.elasticsearch.index.mapper.MapperService.MergeReason;
4243
import org.elasticsearch.indices.IndexTemplateMissingException;
4344
import org.elasticsearch.indices.IndicesService;
4445
import org.elasticsearch.indices.InvalidIndexTemplateException;
@@ -222,7 +223,7 @@ private static void validateAndAddTemplate(final PutRequest request, IndexTempla
222223
mappingsForValidation.put(entry.getKey(), MapperService.parseMapping(entry.getValue()));
223224
}
224225

225-
dummyIndexService.mapperService().merge(mappingsForValidation, false);
226+
dummyIndexService.mapperService().merge(mappingsForValidation, MergeReason.MAPPING_UPDATE, false);
226227

227228
} finally {
228229
if (createdIndex != null) {

core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexUpgradeService.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,7 @@ public Set<Entry<String, NamedAnalyzer>> entrySet() {
147147
};
148148
try (IndexAnalyzers fakeIndexAnalzyers = new IndexAnalyzers(indexSettings, fakeDefault, fakeDefault, fakeDefault, analyzerMap)) {
149149
MapperService mapperService = new MapperService(indexSettings, fakeIndexAnalzyers, similarityService, mapperRegistry, () -> null);
150-
for (ObjectCursor<MappingMetaData> cursor : indexMetaData.getMappings().values()) {
151-
MappingMetaData mappingMetaData = cursor.value;
152-
mapperService.merge(mappingMetaData.type(), mappingMetaData.source(), MapperService.MergeReason.MAPPING_RECOVERY, false);
153-
}
150+
mapperService.merge(indexMetaData, MapperService.MergeReason.MAPPING_RECOVERY, false);
154151
}
155152
} catch (Exception ex) {
156153
// Wrap the inner exception so we have the index name in the exception message

core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.elasticsearch.index.IndexService;
4444
import org.elasticsearch.index.mapper.DocumentMapper;
4545
import org.elasticsearch.index.mapper.MapperService;
46+
import org.elasticsearch.index.mapper.MapperService.MergeReason;
4647
import org.elasticsearch.indices.IndicesService;
4748
import org.elasticsearch.indices.InvalidTypeNameException;
4849

@@ -146,10 +147,7 @@ ClusterState executeRefresh(final ClusterState currentState, final List<RefreshT
146147
// we need to create the index here, and add the current mapping to it, so we can merge
147148
indexService = indicesService.createIndex(indexMetaData, Collections.emptyList(), shardId -> {});
148149
removeIndex = true;
149-
for (ObjectCursor<MappingMetaData> metaData : indexMetaData.getMappings().values()) {
150-
// don't apply the default mapping, it has been applied when the mapping was created
151-
indexService.mapperService().merge(metaData.value.type(), metaData.value.source(), MapperService.MergeReason.MAPPING_RECOVERY, true);
152-
}
150+
indexService.mapperService().merge(indexMetaData, MergeReason.MAPPING_RECOVERY, true);
153151
}
154152

155153
IndexMetaData.Builder builder = IndexMetaData.builder(indexMetaData);
@@ -226,10 +224,7 @@ public BatchResult<PutMappingClusterStateUpdateRequest> execute(ClusterState cur
226224
MapperService mapperService = indicesService.createIndexMapperService(indexMetaData);
227225
indexMapperServices.put(index, mapperService);
228226
// add mappings for all types, we need them for cross-type validation
229-
for (ObjectCursor<MappingMetaData> mapping : indexMetaData.getMappings().values()) {
230-
mapperService.merge(mapping.value.type(), mapping.value.source(),
231-
MapperService.MergeReason.MAPPING_RECOVERY, request.updateAllTypes());
232-
}
227+
mapperService.merge(indexMetaData, MergeReason.MAPPING_RECOVERY, request.updateAllTypes());
233228
}
234229
}
235230
currentState = applyRequest(currentState, request, indexMapperServices);
@@ -313,7 +308,7 @@ private ClusterState applyRequest(ClusterState currentState, PutMappingClusterSt
313308
if (existingMapper != null) {
314309
existingSource = existingMapper.mappingSource();
315310
}
316-
DocumentMapper mergedMapper = mapperService.merge(mappingType, mappingUpdateSource, MapperService.MergeReason.MAPPING_UPDATE, request.updateAllTypes());
311+
DocumentMapper mergedMapper = mapperService.merge(mappingType, mappingUpdateSource, MergeReason.MAPPING_UPDATE, request.updateAllTypes());
317312
CompressedXContent updatedSource = mergedMapper.mappingSource();
318313

319314
if (existingSource != null) {

0 commit comments

Comments
 (0)