improve a bit the speed of adding new fields as part of mapping change / parse

This commit is contained in:
Shay Banon 2012-01-16 21:09:07 +02:00
parent bddea09170
commit 56a9c66df1
2 changed files with 47 additions and 70 deletions

View File

@ -19,10 +19,9 @@
package org.elasticsearch.index.mapper;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
import com.google.common.collect.UnmodifiableIterator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
/**
@ -30,84 +29,61 @@ import java.util.List;
*/
public class FieldMappers implements Iterable<FieldMapper> {
private final ImmutableList<FieldMapper> fieldMappers;
private final FieldMapper[] fieldMappers;
private final List<FieldMapper> fieldMappersAsList;
public FieldMappers() {
this.fieldMappers = ImmutableList.of();
this.fieldMappers = new FieldMapper[0];
this.fieldMappersAsList = Arrays.asList(fieldMappers);
}
public FieldMappers(FieldMapper fieldMapper) {
this(new FieldMapper[]{fieldMapper});
this.fieldMappers = new FieldMapper[]{fieldMapper};
this.fieldMappersAsList = Arrays.asList(this.fieldMappers);
}
public FieldMappers(FieldMapper[] fieldMappers) {
if (fieldMappers == null) {
fieldMappers = new FieldMapper[0];
}
this.fieldMappers = ImmutableList.copyOf(Iterators.forArray(fieldMappers));
}
public FieldMappers(ImmutableList<FieldMapper> fieldMappers) {
private FieldMappers(FieldMapper[] fieldMappers) {
this.fieldMappers = fieldMappers;
this.fieldMappersAsList = Arrays.asList(this.fieldMappers);
}
public FieldMapper mapper() {
if (fieldMappers.isEmpty()) {
if (fieldMappers.length == 0) {
return null;
}
return fieldMappers.get(0);
return fieldMappers[0];
}
public boolean isEmpty() {
return fieldMappers.isEmpty();
return fieldMappers.length == 0;
}
public ImmutableList<FieldMapper> mappers() {
return this.fieldMappers;
public List<FieldMapper> mappers() {
return this.fieldMappersAsList;
}
@Override
public UnmodifiableIterator<FieldMapper> iterator() {
return fieldMappers.iterator();
public Iterator<FieldMapper> iterator() {
return fieldMappersAsList.iterator();
}
/**
* Concats and returns a new {@link FieldMappers}.
*/
public FieldMappers concat(FieldMapper mapper) {
return new FieldMappers(new ImmutableList.Builder<FieldMapper>().addAll(fieldMappers).add(mapper).build());
}
/**
* Concats and returns a new {@link FieldMappers}.
*/
public FieldMappers concat(FieldMappers mappers) {
return new FieldMappers(new ImmutableList.Builder<FieldMapper>().addAll(fieldMappers).addAll(mappers).build());
}
public FieldMappers remove(List<FieldMapper> mappers) {
ImmutableList.Builder<FieldMapper> builder = new ImmutableList.Builder<FieldMapper>();
for (FieldMapper fieldMapper : fieldMappers) {
boolean found = false;
for (FieldMapper mapper : mappers) {
if (fieldMapper.equals(mapper)) { // identify equality
found = true;
}
}
if (!found) {
builder.add(fieldMapper);
}
}
return new FieldMappers(builder.build());
FieldMapper[] newMappers = new FieldMapper[fieldMappers.length + 1];
System.arraycopy(fieldMappers, 0, newMappers, 0, fieldMappers.length);
newMappers[fieldMappers.length] = mapper;
return new FieldMappers(newMappers);
}
public FieldMappers remove(FieldMapper mapper) {
ImmutableList.Builder<FieldMapper> builder = new ImmutableList.Builder<FieldMapper>();
ArrayList<FieldMapper> list = new ArrayList<FieldMapper>(fieldMappers.length);
for (FieldMapper fieldMapper : fieldMappers) {
if (!fieldMapper.equals(mapper)) { // identify equality
builder.add(fieldMapper);
list.add(fieldMapper);
}
}
return new FieldMappers(builder.build());
return new FieldMappers(list.toArray(new FieldMapper[list.size()]));
}
}

View File

@ -21,6 +21,7 @@ package org.elasticsearch.index.mapper;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterators;
import com.google.common.collect.Sets;
import com.google.common.collect.UnmodifiableIterator;
import org.apache.lucene.analysis.Analyzer;
@ -78,14 +79,14 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
private volatile String defaultMappingSource;
private volatile ImmutableMap<String, DocumentMapper> mappers = ImmutableMap.of();
private volatile Map<String, DocumentMapper> mappers = ImmutableMap.of();
private final Object mutex = new Object();
private volatile ImmutableMap<String, FieldMappers> nameFieldMappers = ImmutableMap.of();
private volatile ImmutableMap<String, FieldMappers> indexNameFieldMappers = ImmutableMap.of();
private volatile ImmutableMap<String, FieldMappers> fullNameFieldMappers = ImmutableMap.of();
private volatile ImmutableMap<String, ObjectMappers> objectMappers = ImmutableMap.of();
private volatile Map<String, FieldMappers> nameFieldMappers = ImmutableMap.of();
private volatile Map<String, FieldMappers> indexNameFieldMappers = ImmutableMap.of();
private volatile Map<String, FieldMappers> fullNameFieldMappers = ImmutableMap.of();
private volatile Map<String, ObjectMappers> objectMappers = ImmutableMap.of();
private boolean hasNested = false; // updated dynamically to true when a nested object is added
private final DocumentMapperParser documentParser;
@ -146,7 +147,7 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
@Override
public UnmodifiableIterator<DocumentMapper> iterator() {
return mappers.values().iterator();
return Iterators.unmodifiableIterator(mappers.values().iterator());
}
public AnalysisService analysisService() {
@ -164,7 +165,7 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
// still add it as a document mapper so we have it registered and, for example, persisted back into
// the cluster meta data if needed, or checked for existence
synchronized (mutex) {
mappers = newMapBuilder(mappers).put(type, mapper).immutableMap();
mappers = newMapBuilder(mappers).put(type, mapper).map();
}
defaultMappingSource = mappingSource;
} else {
@ -194,7 +195,7 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
DocumentMapper oldMapper = mappers.get(mapper.type());
mapper.addFieldMapperListener(fieldMapperListener, true);
mapper.addObjectMapperListener(objectMapperListener, true);
mappers = newMapBuilder(mappers).put(mapper.type(), mapper).immutableMap();
mappers = newMapBuilder(mappers).put(mapper.type(), mapper).map();
if (oldMapper != null) {
removeObjectFieldMappers(oldMapper);
oldMapper.close();
@ -209,7 +210,7 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
return;
}
docMapper.close();
mappers = newMapBuilder(mappers).remove(type).immutableMap();
mappers = newMapBuilder(mappers).remove(type).map();
removeObjectFieldMappers(docMapper);
}
}
@ -221,9 +222,9 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
if (mappers != null) {
mappers = mappers.remove(mapper);
if (mappers.isEmpty()) {
nameFieldMappers = newMapBuilder(nameFieldMappers).remove(mapper.names().name()).immutableMap();
nameFieldMappers = newMapBuilder(nameFieldMappers).remove(mapper.names().name()).map();
} else {
nameFieldMappers = newMapBuilder(nameFieldMappers).put(mapper.names().name(), mappers).immutableMap();
nameFieldMappers = newMapBuilder(nameFieldMappers).put(mapper.names().name(), mappers).map();
}
}
@ -231,9 +232,9 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
if (mappers != null) {
mappers = mappers.remove(mapper);
if (mappers.isEmpty()) {
indexNameFieldMappers = newMapBuilder(indexNameFieldMappers).remove(mapper.names().indexName()).immutableMap();
indexNameFieldMappers = newMapBuilder(indexNameFieldMappers).remove(mapper.names().indexName()).map();
} else {
indexNameFieldMappers = newMapBuilder(indexNameFieldMappers).put(mapper.names().indexName(), mappers).immutableMap();
indexNameFieldMappers = newMapBuilder(indexNameFieldMappers).put(mapper.names().indexName(), mappers).map();
}
}
@ -241,9 +242,9 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
if (mappers != null) {
mappers = mappers.remove(mapper);
if (mappers.isEmpty()) {
fullNameFieldMappers = newMapBuilder(fullNameFieldMappers).remove(mapper.names().fullName()).immutableMap();
fullNameFieldMappers = newMapBuilder(fullNameFieldMappers).remove(mapper.names().fullName()).map();
} else {
fullNameFieldMappers = newMapBuilder(fullNameFieldMappers).put(mapper.names().fullName(), mappers).immutableMap();
fullNameFieldMappers = newMapBuilder(fullNameFieldMappers).put(mapper.names().fullName(), mappers).map();
}
}
}
@ -253,9 +254,9 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
if (mappers != null) {
mappers = mappers.remove(mapper);
if (mappers.isEmpty()) {
objectMappers = newMapBuilder(objectMappers).remove(mapper.fullPath()).immutableMap();
objectMappers = newMapBuilder(objectMappers).remove(mapper.fullPath()).map();
} else {
objectMappers = newMapBuilder(objectMappers).put(mapper.fullPath(), mappers).immutableMap();
objectMappers = newMapBuilder(objectMappers).put(mapper.fullPath(), mappers).map();
}
}
}
@ -867,7 +868,7 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
mappers = mappers.concat(fieldMapper);
}
nameFieldMappers = newMapBuilder(nameFieldMappers).put(fieldMapper.names().name(), mappers).immutableMap();
nameFieldMappers = newMapBuilder(nameFieldMappers).put(fieldMapper.names().name(), mappers).map();
mappers = indexNameFieldMappers.get(fieldMapper.names().indexName());
if (mappers == null) {
@ -875,7 +876,7 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
} else {
mappers = mappers.concat(fieldMapper);
}
indexNameFieldMappers = newMapBuilder(indexNameFieldMappers).put(fieldMapper.names().indexName(), mappers).immutableMap();
indexNameFieldMappers = newMapBuilder(indexNameFieldMappers).put(fieldMapper.names().indexName(), mappers).map();
mappers = fullNameFieldMappers.get(fieldMapper.names().fullName());
if (mappers == null) {
@ -883,7 +884,7 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
} else {
mappers = mappers.concat(fieldMapper);
}
fullNameFieldMappers = newMapBuilder(fullNameFieldMappers).put(fieldMapper.names().fullName(), mappers).immutableMap();
fullNameFieldMappers = newMapBuilder(fullNameFieldMappers).put(fieldMapper.names().fullName(), mappers).map();
}
}
}
@ -897,7 +898,7 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
} else {
mappers = mappers.concat(objectMapper);
}
objectMappers = newMapBuilder(objectMappers).put(objectMapper.fullPath(), mappers).immutableMap();
objectMappers = newMapBuilder(objectMappers).put(objectMapper.fullPath(), mappers).map();
// update the hasNested flag
if (objectMapper.nested().isNested()) {
hasNested = true;