parent/child: Fix `_parent.type` validation.

A `_parent` field can only point to a type that doesn't exist yet.
The validation that checks this relied on have all mappings in the
MapperService. The issue is that this check is performed on the
elected master node and it may not have the IndexService at all
to perform this check. In that case it creates a temporary IndexService and
MapperService to perform mapping validation, but only the mappings
that are part of the put index call are created, not the already existing mappings.
Because of that the `_parent` field validation can't be performed.

By changing the validation to rely on the cluster state's IndexMetaData instead
we can get around the issue with the IndexService/MapperService on the elected
master node. The IndexMetaData always holds the MappingMetaData instances
for all types.
This commit is contained in:
Martijn van Groningen 2015-05-31 13:20:49 +02:00
parent d99b5dfdb4
commit 2fe7cde8d1
1 changed files with 7 additions and 3 deletions

View File

@ -19,6 +19,7 @@
package org.elasticsearch.cluster.metadata; package org.elasticsearch.cluster.metadata;
import com.carrotsearch.hppc.cursors.ObjectCursor;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
@ -37,10 +38,10 @@ import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.Index; import org.elasticsearch.index.Index;
import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.mapper.DocumentMapper; import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.MergeMappingException; import org.elasticsearch.index.mapper.MergeMappingException;
import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.mapper.MergeResult; import org.elasticsearch.index.mapper.MergeResult;
import org.elasticsearch.indices.IndexMissingException; import org.elasticsearch.indices.IndexMissingException;
import org.elasticsearch.indices.IndicesService; import org.elasticsearch.indices.IndicesService;
@ -396,8 +397,11 @@ public class MetaDataMappingService extends AbstractComponent {
// and a put mapping api call, so we don't which type did exist before. // and a put mapping api call, so we don't which type did exist before.
// Also the order of the mappings may be backwards. // Also the order of the mappings may be backwards.
if (Version.indexCreated(indexService.getIndexSettings()).onOrAfter(Version.V_2_0_0) && newMapper.parentFieldMapper().active()) { if (Version.indexCreated(indexService.getIndexSettings()).onOrAfter(Version.V_2_0_0) && newMapper.parentFieldMapper().active()) {
if (indexService.mapperService().types().contains(newMapper.parentFieldMapper().type())) { IndexMetaData indexMetaData = currentState.metaData().index(index);
throw new IllegalArgumentException("can't add a _parent field that points to an already existing type"); for (ObjectCursor<MappingMetaData> mapping : indexMetaData.mappings().values()) {
if (newMapper.parentFieldMapper().type().equals(mapping.value.type())) {
throw new IllegalArgumentException("can't add a _parent field that points to an already existing type");
}
} }
} }
} }