mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-03-09 14:34:43 +00:00
Introduce a new ImmutableOpenMap
this map is a "true" immutable map, encapsulating an open impl, and has a builder that allows it to be built easily. the builder has the optimization of using clone if its being built based on an existing immutable map.
This commit is contained in:
parent
a021c1d4f2
commit
c63741db04
@ -0,0 +1,238 @@
|
||||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. ElasticSearch licenses this
|
||||
* file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.common.collect;
|
||||
|
||||
import com.carrotsearch.hppc.*;
|
||||
import com.carrotsearch.hppc.cursors.ObjectObjectCursor;
|
||||
import com.carrotsearch.hppc.predicates.ObjectPredicate;
|
||||
import com.carrotsearch.hppc.procedures.ObjectObjectProcedure;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An immutable map implementation based on open hash map.
|
||||
* <p/>
|
||||
* Can be constructed using a {@link #builder()}, or using {@link #builder(ImmutableOpenMap)} (which is an optimized
|
||||
* option to copy over existing content and modify it).
|
||||
*/
|
||||
public final class ImmutableOpenMap<KType, VType> implements Iterable<ObjectObjectCursor<KType, VType>> {
|
||||
|
||||
private final ObjectObjectOpenHashMap<KType, VType> map;
|
||||
|
||||
private ImmutableOpenMap(ObjectObjectOpenHashMap<KType, VType> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the default value
|
||||
* for the key type, if the key is not associated with any value.
|
||||
* <p/>
|
||||
* <b>Important note:</b> For primitive type values, the value returned for a non-existing
|
||||
* key may not be the default value of the primitive type (it may be any value previously
|
||||
* assigned to that slot).
|
||||
*/
|
||||
public VType get(KType key) {
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this container has an association to a value for
|
||||
* the given key.
|
||||
*/
|
||||
public boolean containsKey(KType key) {
|
||||
return map.containsKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the current size (number of assigned keys) in the container.
|
||||
*/
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Return <code>true</code> if this hash map contains no assigned keys.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cursor over the entries (key-value pairs) in this map. The iterator is
|
||||
* implemented as a cursor and it returns <b>the same cursor instance</b> on every
|
||||
* call to {@link Iterator#next()}. To read the current key and value use the cursor's
|
||||
* public fields. An example is shown below.
|
||||
* <pre>
|
||||
* for (IntShortCursor c : intShortMap)
|
||||
* {
|
||||
* System.out.println("index=" + c.index
|
||||
* + " key=" + c.key
|
||||
* + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
* <p/>
|
||||
* <p>The <code>index</code> field inside the cursor gives the internal index inside
|
||||
* the container's implementation. The interpretation of this index depends on
|
||||
* to the container.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<ObjectObjectCursor<KType, VType>> iterator() {
|
||||
return map.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return map.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ImmutableOpenMap that = (ImmutableOpenMap) o;
|
||||
|
||||
if (!map.equals(that.map)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return map.hashCode();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static final ImmutableOpenMap EMPTY = new ImmutableOpenMap(new ObjectObjectOpenHashMap());
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <KType, VType> ImmutableOpenMap<KType, VType> of() {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
public static <KType, VType> Builder<KType, VType> builder() {
|
||||
return new Builder<KType, VType>();
|
||||
}
|
||||
|
||||
public static <KType, VType> Builder<KType, VType> builder(ImmutableOpenMap<KType, VType> map) {
|
||||
return new Builder<KType, VType>(map);
|
||||
}
|
||||
|
||||
public static class Builder<KType, VType> implements ObjectObjectMap<KType, VType> {
|
||||
|
||||
private final ObjectObjectOpenHashMap<KType, VType> map;
|
||||
|
||||
public Builder() {
|
||||
//noinspection unchecked
|
||||
this(EMPTY);
|
||||
}
|
||||
|
||||
public Builder(ImmutableOpenMap<KType, VType> map) {
|
||||
if (map == EMPTY) {
|
||||
// create a new instance if this is the shared EMPTY one
|
||||
this.map = new ObjectObjectOpenHashMap<KType, VType>();
|
||||
} else {
|
||||
this.map = map.map.clone();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a new instance of the
|
||||
*/
|
||||
public ImmutableOpenMap<KType, VType> build() {
|
||||
return new ImmutableOpenMap<KType, VType>(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VType put(KType key, VType value) {
|
||||
return map.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VType get(KType key) {
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int putAll(ObjectObjectAssociativeContainer<? extends KType, ? extends VType> container) {
|
||||
return map.putAll(container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int putAll(Iterable<? extends ObjectObjectCursor<? extends KType, ? extends VType>> iterable) {
|
||||
return map.putAll(iterable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VType remove(KType key) {
|
||||
return map.remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<ObjectObjectCursor<KType, VType>> iterator() {
|
||||
return map.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(KType key) {
|
||||
return map.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removeAll(ObjectContainer<? extends KType> container) {
|
||||
return map.removeAll(container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int removeAll(ObjectPredicate<? super KType> predicate) {
|
||||
return map.removeAll(predicate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ObjectObjectProcedure<? super KType, ? super VType>> T forEach(T procedure) {
|
||||
return map.forEach(procedure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
map.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectCollection<KType> keys() {
|
||||
return map.keys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectContainer<VType> values() {
|
||||
return map.values();
|
||||
}
|
||||
}
|
||||
}
|
@ -19,25 +19,25 @@
|
||||
|
||||
package org.elasticsearch.index.analysis;
|
||||
|
||||
import com.carrotsearch.hppc.ObjectObjectOpenHashMap;
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.apache.lucene.analysis.AnalyzerWrapper;
|
||||
import org.elasticsearch.common.collect.ImmutableOpenMap;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public final class FieldNameAnalyzer extends AnalyzerWrapper {
|
||||
|
||||
private final ObjectObjectOpenHashMap<String, Analyzer> analyzers;
|
||||
private final ImmutableOpenMap<String, Analyzer> analyzers;
|
||||
|
||||
private final Analyzer defaultAnalyzer;
|
||||
|
||||
public FieldNameAnalyzer(ObjectObjectOpenHashMap<String, Analyzer> analyzers, Analyzer defaultAnalyzer) {
|
||||
public FieldNameAnalyzer(ImmutableOpenMap<String, Analyzer> analyzers, Analyzer defaultAnalyzer) {
|
||||
this.analyzers = analyzers;
|
||||
this.defaultAnalyzer = defaultAnalyzer;
|
||||
}
|
||||
|
||||
public ObjectObjectOpenHashMap<String, Analyzer> analyzers() {
|
||||
public ImmutableOpenMap<String, Analyzer> analyzers() {
|
||||
return analyzers;
|
||||
}
|
||||
|
||||
|
@ -19,11 +19,10 @@
|
||||
|
||||
package org.elasticsearch.index.mapper;
|
||||
|
||||
import com.carrotsearch.hppc.ObjectObjectOpenHashMap;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.UnmodifiableIterator;
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.elasticsearch.common.hppc.HppcMaps;
|
||||
import org.elasticsearch.common.collect.ImmutableOpenMap;
|
||||
import org.elasticsearch.index.analysis.FieldNameAnalyzer;
|
||||
|
||||
import java.util.Set;
|
||||
@ -43,17 +42,17 @@ public class DocumentFieldMappers implements Iterable<FieldMapper> {
|
||||
public DocumentFieldMappers(DocumentMapper docMapper) {
|
||||
this.docMapper = docMapper;
|
||||
this.fieldMappers = new FieldMappersLookup();
|
||||
this.indexAnalyzer = new FieldNameAnalyzer(HppcMaps.<String, Analyzer>newMap(), docMapper.indexAnalyzer());
|
||||
this.searchAnalyzer = new FieldNameAnalyzer(HppcMaps.<String, Analyzer>newMap(), docMapper.searchAnalyzer());
|
||||
this.searchQuoteAnalyzer = new FieldNameAnalyzer(HppcMaps.<String, Analyzer>newMap(), docMapper.searchQuotedAnalyzer());
|
||||
this.indexAnalyzer = new FieldNameAnalyzer(ImmutableOpenMap.<String, Analyzer>of(), docMapper.indexAnalyzer());
|
||||
this.searchAnalyzer = new FieldNameAnalyzer(ImmutableOpenMap.<String, Analyzer>of(), docMapper.searchAnalyzer());
|
||||
this.searchQuoteAnalyzer = new FieldNameAnalyzer(ImmutableOpenMap.<String, Analyzer>of(), docMapper.searchQuotedAnalyzer());
|
||||
}
|
||||
|
||||
public void addNewMappers(Iterable<FieldMapper> newMappers) {
|
||||
fieldMappers.addNewMappers(newMappers);
|
||||
|
||||
final ObjectObjectOpenHashMap<String, Analyzer> indexAnalyzers = this.indexAnalyzer.analyzers().clone();
|
||||
final ObjectObjectOpenHashMap<String, Analyzer> searchAnalyzers = this.searchAnalyzer.analyzers().clone();
|
||||
final ObjectObjectOpenHashMap<String, Analyzer> searchQuoteAnalyzers = this.searchQuoteAnalyzer.analyzers().clone();
|
||||
final ImmutableOpenMap.Builder<String, Analyzer> indexAnalyzers = ImmutableOpenMap.builder(this.indexAnalyzer.analyzers());
|
||||
final ImmutableOpenMap.Builder<String, Analyzer> searchAnalyzers = ImmutableOpenMap.builder(this.searchAnalyzer.analyzers());
|
||||
final ImmutableOpenMap.Builder<String, Analyzer> searchQuoteAnalyzers = ImmutableOpenMap.builder(this.searchQuoteAnalyzer.analyzers());
|
||||
|
||||
for (FieldMapper fieldMapper : newMappers) {
|
||||
if (fieldMapper.indexAnalyzer() != null) {
|
||||
@ -67,9 +66,9 @@ public class DocumentFieldMappers implements Iterable<FieldMapper> {
|
||||
}
|
||||
}
|
||||
|
||||
this.indexAnalyzer = new FieldNameAnalyzer(indexAnalyzers, docMapper.indexAnalyzer());
|
||||
this.searchAnalyzer = new FieldNameAnalyzer(searchAnalyzers, docMapper.searchAnalyzer());
|
||||
this.searchQuoteAnalyzer = new FieldNameAnalyzer(searchQuoteAnalyzers, docMapper.searchQuotedAnalyzer());
|
||||
this.indexAnalyzer = new FieldNameAnalyzer(indexAnalyzers.build(), docMapper.indexAnalyzer());
|
||||
this.searchAnalyzer = new FieldNameAnalyzer(searchAnalyzers.build(), docMapper.searchAnalyzer());
|
||||
this.searchQuoteAnalyzer = new FieldNameAnalyzer(searchQuoteAnalyzers.build(), docMapper.searchQuotedAnalyzer());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -19,12 +19,11 @@
|
||||
|
||||
package org.elasticsearch.index.mapper;
|
||||
|
||||
import com.carrotsearch.hppc.ObjectObjectOpenHashMap;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.common.collect.UnmodifiableIterator;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.hppc.HppcMaps;
|
||||
import org.elasticsearch.common.collect.ImmutableOpenMap;
|
||||
import org.elasticsearch.common.regex.Regex;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -37,24 +36,24 @@ import java.util.Set;
|
||||
public class FieldMappersLookup implements Iterable<FieldMapper> {
|
||||
|
||||
private volatile ImmutableList<FieldMapper> mappers;
|
||||
private volatile ObjectObjectOpenHashMap<String, FieldMappers> name;
|
||||
private volatile ObjectObjectOpenHashMap<String, FieldMappers> indexName;
|
||||
private volatile ObjectObjectOpenHashMap<String, FieldMappers> fullName;
|
||||
private volatile ImmutableOpenMap<String, FieldMappers> name;
|
||||
private volatile ImmutableOpenMap<String, FieldMappers> indexName;
|
||||
private volatile ImmutableOpenMap<String, FieldMappers> fullName;
|
||||
|
||||
public FieldMappersLookup() {
|
||||
this.mappers = ImmutableList.of();
|
||||
this.fullName = HppcMaps.newMap();
|
||||
this.name = HppcMaps.newMap();
|
||||
this.indexName = HppcMaps.newMap();
|
||||
this.fullName = ImmutableOpenMap.of();
|
||||
this.name = ImmutableOpenMap.of();
|
||||
this.indexName = ImmutableOpenMap.of();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new set of mappers.
|
||||
*/
|
||||
public void addNewMappers(Iterable<FieldMapper> newMappers) {
|
||||
final ObjectObjectOpenHashMap<String, FieldMappers> tempName = this.name.clone();
|
||||
final ObjectObjectOpenHashMap<String, FieldMappers> tempIndexName = this.indexName.clone();
|
||||
final ObjectObjectOpenHashMap<String, FieldMappers> tempFullName = this.fullName.clone();
|
||||
final ImmutableOpenMap.Builder<String, FieldMappers> tempName = ImmutableOpenMap.builder(name);
|
||||
final ImmutableOpenMap.Builder<String, FieldMappers> tempIndexName = ImmutableOpenMap.builder(indexName);
|
||||
final ImmutableOpenMap.Builder<String, FieldMappers> tempFullName = ImmutableOpenMap.builder(fullName);
|
||||
|
||||
for (FieldMapper fieldMapper : newMappers) {
|
||||
FieldMappers mappers = tempName.get(fieldMapper.names().name());
|
||||
@ -82,9 +81,9 @@ public class FieldMappersLookup implements Iterable<FieldMapper> {
|
||||
tempFullName.put(fieldMapper.names().fullName(), mappers);
|
||||
}
|
||||
this.mappers = ImmutableList.<FieldMapper>builder().addAll(this.mappers).addAll(newMappers).build();
|
||||
this.name = tempName;
|
||||
this.indexName = tempIndexName;
|
||||
this.fullName = tempFullName;
|
||||
this.name = tempName.build();
|
||||
this.indexName = tempIndexName.build();
|
||||
this.fullName = tempFullName.build();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -92,9 +91,9 @@ public class FieldMappersLookup implements Iterable<FieldMapper> {
|
||||
*/
|
||||
public void removeMappers(Iterable<FieldMapper> mappersToRemove) {
|
||||
List<FieldMapper> tempMappers = new ArrayList<FieldMapper>(this.mappers);
|
||||
ObjectObjectOpenHashMap<String, FieldMappers> tempName = this.name.clone();
|
||||
ObjectObjectOpenHashMap<String, FieldMappers> tempIndexName = this.indexName.clone();
|
||||
ObjectObjectOpenHashMap<String, FieldMappers> tempFullName = this.fullName.clone();
|
||||
ImmutableOpenMap.Builder<String, FieldMappers> tempName = ImmutableOpenMap.builder(this.name);
|
||||
ImmutableOpenMap.Builder<String, FieldMappers> tempIndexName = ImmutableOpenMap.builder(this.indexName);
|
||||
ImmutableOpenMap.Builder<String, FieldMappers> tempFullName = ImmutableOpenMap.builder(this.fullName);
|
||||
|
||||
for (FieldMapper mapper : mappersToRemove) {
|
||||
FieldMappers mappers = tempName.get(mapper.names().name());
|
||||
@ -132,9 +131,9 @@ public class FieldMappersLookup implements Iterable<FieldMapper> {
|
||||
|
||||
|
||||
this.mappers = ImmutableList.copyOf(tempMappers);
|
||||
this.name = tempName;
|
||||
this.indexName = tempIndexName;
|
||||
this.fullName = tempFullName;
|
||||
this.name = tempName.build();
|
||||
this.indexName = tempIndexName.build();
|
||||
this.fullName = tempFullName.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
package org.elasticsearch.index.mapper;
|
||||
|
||||
import com.carrotsearch.hppc.ObjectObjectOpenHashMap;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.collect.*;
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
@ -32,7 +31,7 @@ import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.Filter;
|
||||
import org.apache.lucene.util.BytesRef;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.hppc.HppcMaps;
|
||||
import org.elasticsearch.common.collect.ImmutableOpenMap;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.io.Streams;
|
||||
import org.elasticsearch.common.lucene.search.AndFilter;
|
||||
@ -90,7 +89,7 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
|
||||
private final Object mappersMutex = new Object();
|
||||
|
||||
private final FieldMappersLookup fieldMappers = new FieldMappersLookup();
|
||||
private volatile ObjectObjectOpenHashMap<String, ObjectMappers> fullPathObjectMappers = HppcMaps.newMap();
|
||||
private volatile ImmutableOpenMap<String, ObjectMappers> fullPathObjectMappers = ImmutableOpenMap.of();
|
||||
private boolean hasNested = false; // updated dynamically to true when a nested object is added
|
||||
|
||||
private final DocumentMapperParser documentParser;
|
||||
@ -295,7 +294,7 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
|
||||
|
||||
private void addObjectMappers(ObjectMapper[] objectMappers) {
|
||||
synchronized (mappersMutex) {
|
||||
ObjectObjectOpenHashMap<String, ObjectMappers> fullPathObjectMappers = this.fullPathObjectMappers.clone();
|
||||
ImmutableOpenMap.Builder<String, ObjectMappers> fullPathObjectMappers = ImmutableOpenMap.builder(this.fullPathObjectMappers);
|
||||
for (ObjectMapper objectMapper : objectMappers) {
|
||||
ObjectMappers mappers = fullPathObjectMappers.get(objectMapper.fullPath());
|
||||
if (mappers == null) {
|
||||
@ -309,7 +308,7 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
|
||||
hasNested = true;
|
||||
}
|
||||
}
|
||||
this.fullPathObjectMappers = fullPathObjectMappers;
|
||||
this.fullPathObjectMappers = fullPathObjectMappers.build();
|
||||
}
|
||||
}
|
||||
|
||||
@ -338,7 +337,7 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
|
||||
synchronized (mappersMutex) {
|
||||
fieldMappers.removeMappers(docMapper.mappers());
|
||||
|
||||
ObjectObjectOpenHashMap<String, ObjectMappers> fullPathObjectMappers = this.fullPathObjectMappers.clone();
|
||||
ImmutableOpenMap.Builder<String, ObjectMappers> fullPathObjectMappers = ImmutableOpenMap.builder(this.fullPathObjectMappers);
|
||||
for (ObjectMapper mapper : docMapper.objectMappers().values()) {
|
||||
ObjectMappers mappers = fullPathObjectMappers.get(mapper.fullPath());
|
||||
if (mappers != null) {
|
||||
@ -351,7 +350,7 @@ public class MapperService extends AbstractIndexComponent implements Iterable<Do
|
||||
}
|
||||
}
|
||||
|
||||
this.fullPathObjectMappers = fullPathObjectMappers;
|
||||
this.fullPathObjectMappers = fullPathObjectMappers.build();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user