Shortcut mapping update if the incoming mapping version is the same as the current mapping version (#59517) (#59772)

Currently, when we apply a cluster state change to a shard on a non-master node,
we check to see if the mappings need to be updated by comparing the decompressed
serialized mappings from the update against the serialized version of the shard's
existing mappings. However, we already have a much simpler way of checking this,
by comparing mapping versions on the index metadata of the old and new states.

This commit adds a shortcut to MapperService.updateMappings() that compares
these mapping versions, and ignores the merge if they are equal.
This commit is contained in:
Alan Woodward 2020-07-17 14:53:09 +01:00 committed by GitHub
parent b29d368b52
commit 65f6fb8e94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 16 additions and 14 deletions

View File

@ -219,6 +219,12 @@ public class MapperService extends AbstractIndexComponent implements Closeable {
public boolean updateMapping(final IndexMetadata currentIndexMetadata, final IndexMetadata newIndexMetadata) throws IOException { public boolean updateMapping(final IndexMetadata currentIndexMetadata, final IndexMetadata newIndexMetadata) throws IOException {
assert newIndexMetadata.getIndex().equals(index()) : "index mismatch: expected " + index() assert newIndexMetadata.getIndex().equals(index()) : "index mismatch: expected " + index()
+ " but was " + newIndexMetadata.getIndex(); + " but was " + newIndexMetadata.getIndex();
if (currentIndexMetadata != null && currentIndexMetadata.getMappingVersion() == newIndexMetadata.getMappingVersion()) {
assertMappingVersion(currentIndexMetadata, newIndexMetadata, Collections.emptyMap());
return false;
}
// go over and add the relevant mappings (or update them) // go over and add the relevant mappings (or update them)
Set<String> existingMappers = new HashSet<>(); Set<String> existingMappers = new HashSet<>();
if (mapper != null) { if (mapper != null) {
@ -230,7 +236,7 @@ public class MapperService extends AbstractIndexComponent implements Closeable {
final Map<String, DocumentMapper> updatedEntries; final Map<String, DocumentMapper> updatedEntries;
try { try {
// only update entries if needed // only update entries if needed
updatedEntries = internalMerge(newIndexMetadata, MergeReason.MAPPING_RECOVERY, true); updatedEntries = internalMerge(newIndexMetadata, MergeReason.MAPPING_RECOVERY);
} catch (Exception e) { } catch (Exception e) {
logger.warn(() -> new ParameterizedMessage("[{}] failed to apply mappings", index()), e); logger.warn(() -> new ParameterizedMessage("[{}] failed to apply mappings", index()), e);
throw e; throw e;
@ -278,7 +284,7 @@ public class MapperService extends AbstractIndexComponent implements Closeable {
private void assertMappingVersion( private void assertMappingVersion(
final IndexMetadata currentIndexMetadata, final IndexMetadata currentIndexMetadata,
final IndexMetadata newIndexMetadata, final IndexMetadata newIndexMetadata,
final Map<String, DocumentMapper> updatedEntries) { final Map<String, DocumentMapper> updatedEntries) throws IOException {
if (Assertions.ENABLED if (Assertions.ENABLED
&& currentIndexMetadata != null && currentIndexMetadata != null
&& currentIndexMetadata.getCreationVersion().onOrAfter(Version.V_6_5_0)) { && currentIndexMetadata.getCreationVersion().onOrAfter(Version.V_6_5_0)) {
@ -302,10 +308,14 @@ public class MapperService extends AbstractIndexComponent implements Closeable {
assert currentSource.equals(newSource) : assert currentSource.equals(newSource) :
"expected current mapping [" + currentSource + "] for type [" + mapping.type() + "] " "expected current mapping [" + currentSource + "] for type [" + mapping.type() + "] "
+ "to be the same as new mapping [" + newSource + "]"; + "to be the same as new mapping [" + newSource + "]";
final CompressedXContent mapperSource = new CompressedXContent(Strings.toString(mapper));
assert currentSource.equals(mapperSource) :
"expected current mapping [" + currentSource + "] for type [" + mapping.type() + "] "
+ "to be the same as new mapping [" + mapperSource + "]";
} }
} else { } else {
// if the mapping version is changed, it should increase, there should be updates, and the mapping should be different // the mapping version should increase, there should be updates, and the mapping should be different
final long currentMappingVersion = currentIndexMetadata.getMappingVersion(); final long currentMappingVersion = currentIndexMetadata.getMappingVersion();
final long newMappingVersion = newIndexMetadata.getMappingVersion(); final long newMappingVersion = newIndexMetadata.getMappingVersion();
assert currentMappingVersion < newMappingVersion : assert currentMappingVersion < newMappingVersion :
@ -352,27 +362,19 @@ public class MapperService extends AbstractIndexComponent implements Closeable {
} }
public void merge(IndexMetadata indexMetadata, MergeReason reason) { public void merge(IndexMetadata indexMetadata, MergeReason reason) {
internalMerge(indexMetadata, reason, false); internalMerge(indexMetadata, reason);
} }
public DocumentMapper merge(String type, CompressedXContent mappingSource, MergeReason reason) { public DocumentMapper merge(String type, CompressedXContent mappingSource, MergeReason reason) {
return internalMerge(Collections.singletonMap(type, mappingSource), reason).get(type); return internalMerge(Collections.singletonMap(type, mappingSource), reason).get(type);
} }
private synchronized Map<String, DocumentMapper> internalMerge(IndexMetadata indexMetadata, private synchronized Map<String, DocumentMapper> internalMerge(IndexMetadata indexMetadata, MergeReason reason) {
MergeReason reason, boolean onlyUpdateIfNeeded) {
assert reason != MergeReason.MAPPING_UPDATE_PREFLIGHT; assert reason != MergeReason.MAPPING_UPDATE_PREFLIGHT;
Map<String, CompressedXContent> map = new LinkedHashMap<>(); Map<String, CompressedXContent> map = new LinkedHashMap<>();
for (ObjectCursor<MappingMetadata> cursor : indexMetadata.getMappings().values()) { for (ObjectCursor<MappingMetadata> cursor : indexMetadata.getMappings().values()) {
MappingMetadata mappingMetadata = cursor.value; MappingMetadata mappingMetadata = cursor.value;
if (onlyUpdateIfNeeded) { map.put(mappingMetadata.type(), mappingMetadata.source());
DocumentMapper existingMapper = documentMapper(mappingMetadata.type());
if (existingMapper == null || mappingMetadata.source().equals(existingMapper.mappingSource()) == false) {
map.put(mappingMetadata.type(), mappingMetadata.source());
}
} else {
map.put(mappingMetadata.type(), mappingMetadata.source());
}
} }
return internalMerge(map, reason); return internalMerge(map, reason);
} }