Improved how aliases are handled in the cluster state.
The following changes improved alias creation: * Moved away from ImmutableMap to JCF's UnmodifiableMap. The ImmutableMap always made a copy, whereas the UnmodifiableMap just wraps the target map. * Reducing the number of maps being created during the creation of MetaData and IndexMetadata. * Changed IndexAliasesService's aliases from a copy on write ImmutableMap to ConcurrentMap. Closes #3410
This commit is contained in:
parent
33d8571d1e
commit
a235a55943
|
@ -143,6 +143,10 @@ public class IndicesAliasesRequest extends MasterNodeOperationRequest<IndicesAli
|
|||
return this.aliasActions;
|
||||
}
|
||||
|
||||
public List<AliasAction> getAliasActions() {
|
||||
return aliasActions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Timeout to wait till the put mapping gets acknowledged of all current cluster nodes. Defaults to
|
||||
* <tt>10s</tt>.
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
package org.elasticsearch.action.admin.indices.exists.types;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.elasticsearch.ElasticSearchException;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.support.master.TransportMasterNodeOperationAction;
|
||||
|
@ -33,6 +32,8 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportService;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Types exists transport action.
|
||||
*/
|
||||
|
@ -84,7 +85,7 @@ public class TransportTypesExistsAction extends TransportMasterNodeOperationActi
|
|||
return;
|
||||
}
|
||||
|
||||
ImmutableMap<String, MappingMetaData> mappings = state.metaData().getIndices().get(concreteIndex).mappings();
|
||||
Map<String, MappingMetaData> mappings = state.metaData().getIndices().get(concreteIndex).mappings();
|
||||
if (mappings.isEmpty()) {
|
||||
listener.onResponse(new TypesExistsResponse(false));
|
||||
return;
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
package org.elasticsearch.cluster;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
|
@ -166,8 +165,8 @@ public class ClusterChangedEvent {
|
|||
|
||||
public boolean indicesStateChanged() {
|
||||
if (metaDataChanged()) {
|
||||
ImmutableMap<String,IndexMetaData> indices = state.metaData().indices();
|
||||
ImmutableMap<String,IndexMetaData> previousIndices = previousState.metaData().indices();
|
||||
Map<String,IndexMetaData> indices = state.metaData().indices();
|
||||
Map<String,IndexMetaData> previousIndices = previousState.metaData().indices();
|
||||
|
||||
for (Map.Entry<String, IndexMetaData> entry : indices.entrySet()) {
|
||||
IndexMetaData indexMetaData = entry.getValue();
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.elasticsearch.cluster.metadata;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.elasticsearch.ElasticSearchGenerationException;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.compress.CompressedString;
|
||||
|
@ -30,7 +31,9 @@ import org.elasticsearch.common.xcontent.XContentFactory;
|
|||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -41,15 +44,22 @@ public class AliasMetaData {
|
|||
|
||||
private final CompressedString filter;
|
||||
|
||||
private String indexRouting;
|
||||
private final String indexRouting;
|
||||
|
||||
private String searchRouting;
|
||||
private final String searchRouting;
|
||||
|
||||
private final Set<String> searchRoutingValues;
|
||||
|
||||
private AliasMetaData(String alias, CompressedString filter, String indexRouting, String searchRouting) {
|
||||
this.alias = alias;
|
||||
this.filter = filter;
|
||||
this.indexRouting = indexRouting;
|
||||
this.searchRouting = searchRouting;
|
||||
if (searchRouting != null) {
|
||||
searchRoutingValues = Collections.unmodifiableSet(Strings.splitStringByCommaToSet(searchRouting));
|
||||
} else {
|
||||
searchRoutingValues = ImmutableSet.of();
|
||||
}
|
||||
}
|
||||
|
||||
public String alias() {
|
||||
|
@ -68,6 +78,10 @@ public class AliasMetaData {
|
|||
return filter();
|
||||
}
|
||||
|
||||
public boolean filteringRequired() {
|
||||
return filter != null;
|
||||
}
|
||||
|
||||
public String getSearchRouting() {
|
||||
return searchRouting();
|
||||
}
|
||||
|
@ -84,6 +98,10 @@ public class AliasMetaData {
|
|||
return indexRouting;
|
||||
}
|
||||
|
||||
public Set<String> searchRoutingValues() {
|
||||
return searchRoutingValues;
|
||||
}
|
||||
|
||||
public static Builder builder(String alias) {
|
||||
return new Builder(alias);
|
||||
}
|
||||
|
|
|
@ -161,13 +161,13 @@ public class IndexMetaData {
|
|||
|
||||
private final State state;
|
||||
|
||||
private final ImmutableMap<String, AliasMetaData> aliases;
|
||||
private final Map<String, AliasMetaData> aliases;
|
||||
|
||||
private final Settings settings;
|
||||
|
||||
private final ImmutableMap<String, MappingMetaData> mappings;
|
||||
private final Map<String, MappingMetaData> mappings;
|
||||
|
||||
private final ImmutableMap<String, Custom> customs;
|
||||
private final Map<String, Custom> customs;
|
||||
|
||||
private transient final int totalNumberOfShards;
|
||||
|
||||
|
@ -175,7 +175,7 @@ public class IndexMetaData {
|
|||
private final DiscoveryNodeFilters includeFilters;
|
||||
private final DiscoveryNodeFilters excludeFilters;
|
||||
|
||||
private IndexMetaData(String index, long version, State state, Settings settings, ImmutableMap<String, MappingMetaData> mappings, ImmutableMap<String, AliasMetaData> aliases, ImmutableMap<String, Custom> customs) {
|
||||
private IndexMetaData(String index, long version, State state, Settings settings, Map<String, MappingMetaData> mappings, Map<String, AliasMetaData> aliases, Map<String, Custom> customs) {
|
||||
Preconditions.checkArgument(settings.getAsInt(SETTING_NUMBER_OF_SHARDS, -1) != -1, "must specify numberOfShards for index [" + index + "]");
|
||||
Preconditions.checkArgument(settings.getAsInt(SETTING_NUMBER_OF_REPLICAS, -1) != -1, "must specify numberOfReplicas for index [" + index + "]");
|
||||
this.index = index;
|
||||
|
@ -264,19 +264,19 @@ public class IndexMetaData {
|
|||
return settings();
|
||||
}
|
||||
|
||||
public ImmutableMap<String, AliasMetaData> aliases() {
|
||||
public Map<String, AliasMetaData> aliases() {
|
||||
return this.aliases;
|
||||
}
|
||||
|
||||
public ImmutableMap<String, AliasMetaData> getAliases() {
|
||||
public Map<String, AliasMetaData> getAliases() {
|
||||
return aliases();
|
||||
}
|
||||
|
||||
public ImmutableMap<String, MappingMetaData> mappings() {
|
||||
public Map<String, MappingMetaData> mappings() {
|
||||
return mappings;
|
||||
}
|
||||
|
||||
public ImmutableMap<String, MappingMetaData> getMappings() {
|
||||
public Map<String, MappingMetaData> getMappings() {
|
||||
return mappings();
|
||||
}
|
||||
|
||||
|
@ -301,11 +301,11 @@ public class IndexMetaData {
|
|||
return mappings.get(MapperService.DEFAULT_MAPPING);
|
||||
}
|
||||
|
||||
public ImmutableMap<String, Custom> customs() {
|
||||
public Map<String, Custom> customs() {
|
||||
return this.customs;
|
||||
}
|
||||
|
||||
public ImmutableMap<String, Custom> getCustoms() {
|
||||
public Map<String, Custom> getCustoms() {
|
||||
return this.customs;
|
||||
}
|
||||
|
||||
|
@ -508,7 +508,7 @@ public class IndexMetaData {
|
|||
AliasMetaData aliasMd = AliasMetaData.newAliasMetaDataBuilder(alias).build();
|
||||
tmpAliases.put(alias, aliasMd);
|
||||
}
|
||||
tmpAliases.putAll(aliases.immutableMap());
|
||||
tmpAliases.putAll(aliases.map());
|
||||
// Remove index.aliases from settings once they are migrated to the new data structure
|
||||
tmpSettings = ImmutableSettings.settingsBuilder().put(settings).putArray("index.aliases").build();
|
||||
}
|
||||
|
@ -521,7 +521,7 @@ public class IndexMetaData {
|
|||
}
|
||||
}
|
||||
|
||||
return new IndexMetaData(index, version, state, tmpSettings, mappings.immutableMap(), tmpAliases.immutableMap(), customs.immutableMap());
|
||||
return new IndexMetaData(index, version, state, tmpSettings, mappings.readOnlyMap(), tmpAliases.readOnlyMap(), customs.readOnlyMap());
|
||||
}
|
||||
|
||||
public static void toXContent(IndexMetaData indexMetaData, XContentBuilder builder, ToXContent.Params params) throws IOException {
|
||||
|
|
|
@ -22,6 +22,8 @@ package org.elasticsearch.cluster.metadata;
|
|||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.*;
|
||||
import gnu.trove.set.hash.THashSet;
|
||||
import org.apache.lucene.util.ArrayUtil;
|
||||
import org.apache.lucene.util.RamUsageEstimator;
|
||||
import org.elasticsearch.ElasticSearchIllegalArgumentException;
|
||||
import org.elasticsearch.action.support.IgnoreIndices;
|
||||
import org.elasticsearch.cluster.block.ClusterBlock;
|
||||
|
@ -29,12 +31,14 @@ import org.elasticsearch.cluster.block.ClusterBlockLevel;
|
|||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.collect.MapBuilder;
|
||||
import org.elasticsearch.common.collect.XMaps;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.regex.Regex;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.settings.loader.SettingsLoader;
|
||||
import org.elasticsearch.common.trove.ExtTHashMap;
|
||||
import org.elasticsearch.common.xcontent.*;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.indices.IndexMissingException;
|
||||
|
@ -46,7 +50,6 @@ import java.util.*;
|
|||
|
||||
import static com.google.common.collect.Lists.newArrayList;
|
||||
import static com.google.common.collect.Maps.newHashMap;
|
||||
import static com.google.common.collect.Sets.newHashSet;
|
||||
import static org.elasticsearch.common.collect.MapBuilder.newMapBuilder;
|
||||
import static org.elasticsearch.common.settings.ImmutableSettings.*;
|
||||
|
||||
|
@ -105,9 +108,9 @@ public class MetaData implements Iterable<IndexMetaData> {
|
|||
private final Settings transientSettings;
|
||||
private final Settings persistentSettings;
|
||||
private final Settings settings;
|
||||
private final ImmutableMap<String, IndexMetaData> indices;
|
||||
private final ImmutableMap<String, IndexTemplateMetaData> templates;
|
||||
private final ImmutableMap<String, Custom> customs;
|
||||
private final Map<String, IndexMetaData> indices;
|
||||
private final Map<String, IndexTemplateMetaData> templates;
|
||||
private final Map<String, Custom> customs;
|
||||
|
||||
private final transient int totalNumberOfShards; // Transient ? not serializable anyway?
|
||||
private final int numberOfShards;
|
||||
|
@ -117,29 +120,24 @@ public class MetaData implements Iterable<IndexMetaData> {
|
|||
private final ImmutableSet<String> allIndicesSet;
|
||||
private final String[] allOpenIndices;
|
||||
|
||||
private final ImmutableMap<String, ImmutableMap<String, AliasMetaData>> aliases;
|
||||
private final Map<String, Map<String, AliasMetaData>> aliases;
|
||||
private final Map<String, StringArray> aliasAndIndexToIndexMap;
|
||||
|
||||
private final ImmutableMap<String, ImmutableMap<String, ImmutableSet<String>>> aliasToIndexToSearchRoutingMap;
|
||||
|
||||
// This map indicates if an alias associated with an index is filtering alias
|
||||
private final ImmutableMap<String, ImmutableMap<String, Boolean>> indexToAliasFilteringRequiredMap;
|
||||
|
||||
private final ImmutableMap<String, String[]> aliasAndIndexToIndexMap;
|
||||
|
||||
|
||||
MetaData(long version, Settings transientSettings, Settings persistentSettings, ImmutableMap<String, IndexMetaData> indices, ImmutableMap<String, IndexTemplateMetaData> templates, ImmutableMap<String, Custom> customs) {
|
||||
MetaData(long version, Settings transientSettings, Settings persistentSettings, Map<String, IndexMetaData> indices, Map<String, IndexTemplateMetaData> templates, Map<String, Custom> customs) {
|
||||
this.version = version;
|
||||
this.transientSettings = transientSettings;
|
||||
this.persistentSettings = persistentSettings;
|
||||
this.settings = ImmutableSettings.settingsBuilder().put(persistentSettings).put(transientSettings).build();
|
||||
this.indices = ImmutableMap.copyOf(indices);
|
||||
this.indices = indices;
|
||||
this.customs = customs;
|
||||
this.templates = templates;
|
||||
int totalNumberOfShards = 0;
|
||||
int numberOfShards = 0;
|
||||
int numAliases = 0;
|
||||
for (IndexMetaData indexMetaData : indices.values()) {
|
||||
totalNumberOfShards += indexMetaData.totalNumberOfShards();
|
||||
numberOfShards += indexMetaData.numberOfShards();
|
||||
numAliases += indexMetaData.aliases().size();
|
||||
}
|
||||
this.totalNumberOfShards = totalNumberOfShards;
|
||||
this.numberOfShards = numberOfShards;
|
||||
|
@ -151,6 +149,7 @@ public class MetaData implements Iterable<IndexMetaData> {
|
|||
}
|
||||
allIndices = allIndicesLst.toArray(new String[allIndicesLst.size()]);
|
||||
allIndicesSet = ImmutableSet.copyOf(allIndices);
|
||||
int numIndices = allIndicesSet.size();
|
||||
|
||||
List<String> allOpenIndices = Lists.newArrayList();
|
||||
for (IndexMetaData indexMetaData : indices.values()) {
|
||||
|
@ -161,88 +160,49 @@ public class MetaData implements Iterable<IndexMetaData> {
|
|||
this.allOpenIndices = allOpenIndices.toArray(new String[allOpenIndices.size()]);
|
||||
|
||||
// build aliases map
|
||||
MapBuilder<String, MapBuilder<String, AliasMetaData>> tmpAliasesMap = newMapBuilder();
|
||||
ExtTHashMap<String, Map<String, AliasMetaData>> aliases = new ExtTHashMap<String, Map<String, AliasMetaData>>(numAliases);
|
||||
for (IndexMetaData indexMetaData : indices.values()) {
|
||||
String index = indexMetaData.index();
|
||||
for (AliasMetaData aliasMd : indexMetaData.aliases().values()) {
|
||||
MapBuilder<String, AliasMetaData> indexAliasMap = tmpAliasesMap.get(aliasMd.alias());
|
||||
Map<String, AliasMetaData> indexAliasMap = aliases.get(aliasMd.alias());
|
||||
if (indexAliasMap == null) {
|
||||
indexAliasMap = newMapBuilder();
|
||||
tmpAliasesMap.put(aliasMd.alias(), indexAliasMap);
|
||||
indexAliasMap = new ExtTHashMap<String, AliasMetaData>(indices.size());
|
||||
aliases.put(aliasMd.alias(), indexAliasMap);
|
||||
}
|
||||
indexAliasMap.put(index, aliasMd);
|
||||
}
|
||||
}
|
||||
MapBuilder<String, ImmutableMap<String, AliasMetaData>> aliases = newMapBuilder();
|
||||
for (Map.Entry<String, MapBuilder<String, AliasMetaData>> alias : tmpAliasesMap.map().entrySet()) {
|
||||
aliases.put(alias.getKey(), alias.getValue().immutableMap());
|
||||
}
|
||||
this.aliases = aliases.immutableMap();
|
||||
|
||||
// build routing aliases set
|
||||
MapBuilder<String, MapBuilder<String, ImmutableSet<String>>> tmpAliasToIndexToSearchRoutingMap = newMapBuilder();
|
||||
for (IndexMetaData indexMetaData : indices.values()) {
|
||||
for (AliasMetaData aliasMd : indexMetaData.aliases().values()) {
|
||||
MapBuilder<String, ImmutableSet<String>> indexToSearchRoutingMap = tmpAliasToIndexToSearchRoutingMap.get(aliasMd.alias());
|
||||
if (indexToSearchRoutingMap == null) {
|
||||
indexToSearchRoutingMap = newMapBuilder();
|
||||
tmpAliasToIndexToSearchRoutingMap.put(aliasMd.alias(), indexToSearchRoutingMap);
|
||||
}
|
||||
if (aliasMd.searchRouting() != null) {
|
||||
indexToSearchRoutingMap.put(indexMetaData.index(), ImmutableSet.copyOf(Strings.splitStringByCommaToSet(aliasMd.searchRouting())));
|
||||
} else {
|
||||
indexToSearchRoutingMap.put(indexMetaData.index(), ImmutableSet.<String>of());
|
||||
}
|
||||
for (int i = 0; i < aliases.internalValues().length; i++) {
|
||||
if (aliases.internalValues()[i] != null) {
|
||||
aliases.internalValues()[i] = XMaps.makeReadOnly((Map) aliases.internalValues()[i]);
|
||||
}
|
||||
}
|
||||
MapBuilder<String, ImmutableMap<String, ImmutableSet<String>>> aliasToIndexToSearchRoutingMap = newMapBuilder();
|
||||
for (Map.Entry<String, MapBuilder<String, ImmutableSet<String>>> alias : tmpAliasToIndexToSearchRoutingMap.map().entrySet()) {
|
||||
aliasToIndexToSearchRoutingMap.put(alias.getKey(), alias.getValue().immutableMap());
|
||||
}
|
||||
this.aliasToIndexToSearchRoutingMap = aliasToIndexToSearchRoutingMap.immutableMap();
|
||||
this.aliases = XMaps.makeReadOnly(aliases);
|
||||
|
||||
// build filtering required map
|
||||
MapBuilder<String, ImmutableMap<String, Boolean>> filteringRequiredMap = newMapBuilder();
|
||||
ExtTHashMap<String, StringArray> aliasAndIndexToIndexMap = new ExtTHashMap<String, StringArray>(numAliases + numIndices);
|
||||
for (IndexMetaData indexMetaData : indices.values()) {
|
||||
MapBuilder<String, Boolean> indexFilteringRequiredMap = newMapBuilder();
|
||||
// Filtering is not required for the index itself
|
||||
indexFilteringRequiredMap.put(indexMetaData.index(), false);
|
||||
for (AliasMetaData aliasMetaData : indexMetaData.aliases().values()) {
|
||||
if (aliasMetaData.filter() != null) {
|
||||
indexFilteringRequiredMap.put(aliasMetaData.alias(), true);
|
||||
} else {
|
||||
indexFilteringRequiredMap.put(aliasMetaData.alias(), false);
|
||||
}
|
||||
StringArray indicesLst = aliasAndIndexToIndexMap.get(indexMetaData.index());
|
||||
if (indicesLst == null) {
|
||||
indicesLst = new StringArray();
|
||||
aliasAndIndexToIndexMap.put(indexMetaData.index(), indicesLst);
|
||||
}
|
||||
filteringRequiredMap.put(indexMetaData.index(), indexFilteringRequiredMap.immutableMap());
|
||||
}
|
||||
indexToAliasFilteringRequiredMap = filteringRequiredMap.immutableMap();
|
||||
|
||||
// build aliasAndIndex to Index map
|
||||
MapBuilder<String, Set<String>> tmpAliasAndIndexToIndexBuilder = newMapBuilder();
|
||||
for (IndexMetaData indexMetaData : indices.values()) {
|
||||
Set<String> lst = tmpAliasAndIndexToIndexBuilder.get(indexMetaData.index());
|
||||
if (lst == null) {
|
||||
lst = newHashSet();
|
||||
tmpAliasAndIndexToIndexBuilder.put(indexMetaData.index(), lst);
|
||||
}
|
||||
lst.add(indexMetaData.index());
|
||||
indicesLst.add(indexMetaData.index());
|
||||
|
||||
for (String alias : indexMetaData.aliases().keySet()) {
|
||||
lst = tmpAliasAndIndexToIndexBuilder.get(alias);
|
||||
if (lst == null) {
|
||||
lst = newHashSet();
|
||||
tmpAliasAndIndexToIndexBuilder.put(alias, lst);
|
||||
indicesLst = aliasAndIndexToIndexMap.get(alias);
|
||||
if (indicesLst == null) {
|
||||
indicesLst = new StringArray();
|
||||
aliasAndIndexToIndexMap.put(alias, indicesLst);
|
||||
}
|
||||
lst.add(indexMetaData.index());
|
||||
indicesLst.add(indexMetaData.index());
|
||||
}
|
||||
}
|
||||
|
||||
MapBuilder<String, String[]> aliasAndIndexToIndexBuilder = newMapBuilder();
|
||||
for (Map.Entry<String, Set<String>> entry : tmpAliasAndIndexToIndexBuilder.map().entrySet()) {
|
||||
aliasAndIndexToIndexBuilder.put(entry.getKey(), entry.getValue().toArray(new String[entry.getValue().size()]));
|
||||
for (StringArray stringArray : aliasAndIndexToIndexMap.values()) {
|
||||
stringArray.trim();
|
||||
}
|
||||
this.aliasAndIndexToIndexMap = aliasAndIndexToIndexBuilder.immutableMap();
|
||||
|
||||
this.aliasAndIndexToIndexMap = XMaps.makeReadOnly(aliasAndIndexToIndexMap);
|
||||
}
|
||||
|
||||
public long version() {
|
||||
|
@ -264,11 +224,11 @@ public class MetaData implements Iterable<IndexMetaData> {
|
|||
return this.persistentSettings;
|
||||
}
|
||||
|
||||
public ImmutableMap<String, ImmutableMap<String, AliasMetaData>> aliases() {
|
||||
public Map<String, Map<String, AliasMetaData>> aliases() {
|
||||
return this.aliases;
|
||||
}
|
||||
|
||||
public ImmutableMap<String, ImmutableMap<String, AliasMetaData>> getAliases() {
|
||||
public Map<String, Map<String, AliasMetaData>> getAliases() {
|
||||
return aliases();
|
||||
}
|
||||
|
||||
|
@ -438,7 +398,7 @@ public class MetaData implements Iterable<IndexMetaData> {
|
|||
*/
|
||||
public String resolveIndexRouting(@Nullable String routing, String aliasOrIndex) {
|
||||
// Check if index is specified by an alias
|
||||
ImmutableMap<String, AliasMetaData> indexAliases = aliases.get(aliasOrIndex);
|
||||
Map<String, AliasMetaData> indexAliases = aliases.get(aliasOrIndex);
|
||||
if (indexAliases == null || indexAliases.isEmpty()) {
|
||||
return routing;
|
||||
}
|
||||
|
@ -486,11 +446,11 @@ public class MetaData implements Iterable<IndexMetaData> {
|
|||
}
|
||||
|
||||
for (String aliasOrIndex : aliasesOrIndices) {
|
||||
ImmutableMap<String, ImmutableSet<String>> indexToRoutingMap = aliasToIndexToSearchRoutingMap.get(aliasOrIndex);
|
||||
Map<String, AliasMetaData> indexToRoutingMap = aliases.get(aliasOrIndex);
|
||||
if (indexToRoutingMap != null && !indexToRoutingMap.isEmpty()) {
|
||||
for (Map.Entry<String, ImmutableSet<String>> indexRouting : indexToRoutingMap.entrySet()) {
|
||||
for (Map.Entry<String, AliasMetaData> indexRouting : indexToRoutingMap.entrySet()) {
|
||||
if (!norouting.contains(indexRouting.getKey())) {
|
||||
if (!indexRouting.getValue().isEmpty()) {
|
||||
if (!indexRouting.getValue().searchRoutingValues().isEmpty()) {
|
||||
// Routing alias
|
||||
if (routings == null) {
|
||||
routings = newHashMap();
|
||||
|
@ -500,7 +460,7 @@ public class MetaData implements Iterable<IndexMetaData> {
|
|||
r = new THashSet<String>();
|
||||
routings.put(indexRouting.getKey(), r);
|
||||
}
|
||||
r.addAll(indexRouting.getValue());
|
||||
r.addAll(indexRouting.getValue().searchRoutingValues());
|
||||
if (paramRouting != null) {
|
||||
r.retainAll(paramRouting);
|
||||
}
|
||||
|
@ -558,13 +518,13 @@ public class MetaData implements Iterable<IndexMetaData> {
|
|||
paramRouting = Strings.splitStringByCommaToSet(routing);
|
||||
}
|
||||
|
||||
ImmutableMap<String, ImmutableSet<String>> indexToRoutingMap = aliasToIndexToSearchRoutingMap.get(aliasOrIndex);
|
||||
Map<String, AliasMetaData> indexToRoutingMap = aliases.get(aliasOrIndex);
|
||||
if (indexToRoutingMap != null && !indexToRoutingMap.isEmpty()) {
|
||||
// It's an alias
|
||||
for (Map.Entry<String, ImmutableSet<String>> indexRouting : indexToRoutingMap.entrySet()) {
|
||||
if (!indexRouting.getValue().isEmpty()) {
|
||||
for (Map.Entry<String, AliasMetaData> indexRouting : indexToRoutingMap.entrySet()) {
|
||||
if (!indexRouting.getValue().searchRoutingValues().isEmpty()) {
|
||||
// Routing alias
|
||||
Set<String> r = new THashSet<String>(indexRouting.getValue());
|
||||
Set<String> r = new THashSet<String>(indexRouting.getValue().searchRoutingValues());
|
||||
if (paramRouting != null) {
|
||||
r.retainAll(paramRouting);
|
||||
}
|
||||
|
@ -639,11 +599,11 @@ public class MetaData implements Iterable<IndexMetaData> {
|
|||
if (this.indices.containsKey(aliasOrIndex)) {
|
||||
return aliasesOrIndices;
|
||||
}
|
||||
String[] actualLst = aliasAndIndexToIndexMap.get(aliasOrIndex);
|
||||
StringArray actualLst = aliasAndIndexToIndexMap.get(aliasOrIndex);
|
||||
if (actualLst == null) {
|
||||
throw new IndexMissingException(new Index(aliasOrIndex));
|
||||
} else {
|
||||
return actualLst;
|
||||
return actualLst.values;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -662,13 +622,13 @@ public class MetaData implements Iterable<IndexMetaData> {
|
|||
|
||||
Set<String> actualIndices = new THashSet<String>();
|
||||
for (String index : aliasesOrIndices) {
|
||||
String[] actualLst = aliasAndIndexToIndexMap.get(index);
|
||||
StringArray actualLst = aliasAndIndexToIndexMap.get(index);
|
||||
if (actualLst == null) {
|
||||
if (ignoreIndices != IgnoreIndices.MISSING) {
|
||||
throw new IndexMissingException(new Index(index));
|
||||
}
|
||||
} else {
|
||||
for (String x : actualLst) {
|
||||
for (String x : actualLst.values) {
|
||||
actualIndices.add(x);
|
||||
}
|
||||
}
|
||||
|
@ -686,14 +646,14 @@ public class MetaData implements Iterable<IndexMetaData> {
|
|||
return index;
|
||||
}
|
||||
// not an actual index, fetch from an alias
|
||||
String[] lst = aliasAndIndexToIndexMap.get(index);
|
||||
StringArray lst = aliasAndIndexToIndexMap.get(index);
|
||||
if (lst == null) {
|
||||
throw new IndexMissingException(new Index(index));
|
||||
}
|
||||
if (lst.length > 1) {
|
||||
throw new ElasticSearchIllegalArgumentException("Alias [" + index + "] has more than one indices associated with it [" + Arrays.toString(lst) + "], can't execute a single index op");
|
||||
if (lst.values.length > 1) {
|
||||
throw new ElasticSearchIllegalArgumentException("Alias [" + index + "] has more than one indices associated with it [" + Arrays.toString(lst.values) + "], can't execute a single index op");
|
||||
}
|
||||
return lst[0];
|
||||
return lst.values[0];
|
||||
}
|
||||
|
||||
public String[] convertFromWildcards(String[] aliasesOrIndices, boolean wildcardOnlyOpen, IgnoreIndices ignoreIndices) {
|
||||
|
@ -780,27 +740,27 @@ public class MetaData implements Iterable<IndexMetaData> {
|
|||
return indices.get(index);
|
||||
}
|
||||
|
||||
public ImmutableMap<String, IndexMetaData> indices() {
|
||||
public Map<String, IndexMetaData> indices() {
|
||||
return this.indices;
|
||||
}
|
||||
|
||||
public ImmutableMap<String, IndexMetaData> getIndices() {
|
||||
public Map<String, IndexMetaData> getIndices() {
|
||||
return indices();
|
||||
}
|
||||
|
||||
public ImmutableMap<String, IndexTemplateMetaData> templates() {
|
||||
public Map<String, IndexTemplateMetaData> templates() {
|
||||
return this.templates;
|
||||
}
|
||||
|
||||
public ImmutableMap<String, IndexTemplateMetaData> getTemplates() {
|
||||
public Map<String, IndexTemplateMetaData> getTemplates() {
|
||||
return this.templates;
|
||||
}
|
||||
|
||||
public ImmutableMap<String, Custom> customs() {
|
||||
public Map<String, Custom> customs() {
|
||||
return this.customs;
|
||||
}
|
||||
|
||||
public ImmutableMap<String, Custom> getCustoms() {
|
||||
public Map<String, Custom> getCustoms() {
|
||||
return this.customs;
|
||||
}
|
||||
|
||||
|
@ -828,35 +788,42 @@ public class MetaData implements Iterable<IndexMetaData> {
|
|||
* <p>Only aliases with filters are returned. If the indices list contains a non-filtering reference to
|
||||
* the index itself - null is returned. Returns <tt>null</tt> if no filtering is required.</p>
|
||||
*/
|
||||
public String[] filteringAliases(String index, String... indices) {
|
||||
if (isAllIndices(indices)) {
|
||||
public String[] filteringAliases(String index, String... indicesOrAliases) {
|
||||
if (isAllIndices(indicesOrAliases)) {
|
||||
return null;
|
||||
}
|
||||
// optimize for the most common single index/alias scenario
|
||||
if (indices.length == 1) {
|
||||
String alias = indices[0];
|
||||
ImmutableMap<String, Boolean> aliasToFilteringRequiredMap = indexToAliasFilteringRequiredMap.get(index);
|
||||
if (aliasToFilteringRequiredMap == null) {
|
||||
if (indicesOrAliases.length == 1) {
|
||||
String alias = indicesOrAliases[0];
|
||||
IndexMetaData indexMetaData = this.indices.get(index);
|
||||
if (indexMetaData == null) {
|
||||
// Shouldn't happen
|
||||
throw new IndexMissingException(new Index(index));
|
||||
}
|
||||
Boolean filteringRequired = aliasToFilteringRequiredMap.get(alias);
|
||||
if (filteringRequired == null || !filteringRequired) {
|
||||
AliasMetaData aliasMetaData = indexMetaData.aliases().get(alias);
|
||||
boolean filteringRequired = aliasMetaData != null && aliasMetaData.filteringRequired();
|
||||
if (!filteringRequired) {
|
||||
return null;
|
||||
}
|
||||
return new String[]{alias};
|
||||
}
|
||||
List<String> filteringAliases = null;
|
||||
for (String alias : indices) {
|
||||
ImmutableMap<String, Boolean> aliasToFilteringRequiredMap = indexToAliasFilteringRequiredMap.get(index);
|
||||
if (aliasToFilteringRequiredMap == null) {
|
||||
for (String alias : indicesOrAliases) {
|
||||
if (alias.equals(index)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
IndexMetaData indexMetaData = this.indices.get(index);
|
||||
if (indexMetaData == null) {
|
||||
// Shouldn't happen
|
||||
throw new IndexMissingException(new Index(index));
|
||||
}
|
||||
Boolean filteringRequired = aliasToFilteringRequiredMap.get(alias);
|
||||
|
||||
AliasMetaData aliasMetaData = indexMetaData.aliases().get(alias);
|
||||
// Check that this is an alias for the current index
|
||||
// Otherwise - skip it
|
||||
if (filteringRequired != null) {
|
||||
if (aliasMetaData != null) {
|
||||
boolean filteringRequired = aliasMetaData.filteringRequired();
|
||||
if (filteringRequired) {
|
||||
// If filtering required - add it to the list of filters
|
||||
if (filteringAliases == null) {
|
||||
|
@ -925,7 +892,7 @@ public class MetaData implements Iterable<IndexMetaData> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public UnmodifiableIterator<IndexMetaData> iterator() {
|
||||
public Iterator<IndexMetaData> iterator() {
|
||||
return indices.values().iterator();
|
||||
}
|
||||
|
||||
|
@ -1082,7 +1049,7 @@ public class MetaData implements Iterable<IndexMetaData> {
|
|||
}
|
||||
|
||||
public MetaData build() {
|
||||
return new MetaData(version, transientSettings, persistentSettings, indices.immutableMap(), templates.immutableMap(), customs.immutableMap());
|
||||
return new MetaData(version, transientSettings, persistentSettings, indices.readOnlyMap(), templates.readOnlyMap(), customs.readOnlyMap());
|
||||
}
|
||||
|
||||
public static String toXContent(MetaData metaData) throws IOException {
|
||||
|
@ -1224,4 +1191,35 @@ public class MetaData implements Iterable<IndexMetaData> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class StringArray {
|
||||
|
||||
String[] values = new String[1];
|
||||
int head = 0;
|
||||
|
||||
void add(String value) {
|
||||
if (head == values.length) {
|
||||
grow();
|
||||
}
|
||||
values[head++] = value;
|
||||
}
|
||||
|
||||
void grow() {
|
||||
int newSize = values.length + 1;
|
||||
String[] newValues = new String[ArrayUtil.oversize(newSize, RamUsageEstimator.NUM_BYTES_OBJECT_REF)];
|
||||
System.arraycopy(values, 0, newValues, 0, values.length);
|
||||
values = newValues;
|
||||
}
|
||||
|
||||
void trim() {
|
||||
if (values.length == head) {
|
||||
return;
|
||||
}
|
||||
|
||||
String[] newValues = new String[head];
|
||||
System.arraycopy(values, 0, newValues, 0, head);
|
||||
values = newValues;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,6 +110,7 @@ public class MetaDataIndexAliasesService extends AbstractComponent {
|
|||
if (indexMetaData == null) {
|
||||
throw new IndexMissingException(new Index(aliasAction.index()));
|
||||
}
|
||||
// TODO: not copy (putAll)
|
||||
IndexMetaData.Builder indexMetaDataBuilder = newIndexMetaDataBuilder(indexMetaData);
|
||||
if (aliasAction.actionType() == AliasAction.Type.ADD) {
|
||||
String filter = aliasAction.filter();
|
||||
|
|
|
@ -80,6 +80,10 @@ public class MapBuilder<K, V> {
|
|||
return this.map;
|
||||
}
|
||||
|
||||
public Map<K, V> readOnlyMap() {
|
||||
return XMaps.makeReadOnly(map);
|
||||
}
|
||||
|
||||
public ImmutableMap<K, V> immutableMap() {
|
||||
return ImmutableMap.copyOf(map);
|
||||
}
|
||||
|
|
|
@ -19,14 +19,13 @@
|
|||
|
||||
package org.elasticsearch.common.collect;
|
||||
|
||||
import com.google.common.collect.ForwardingMap;
|
||||
import gnu.trove.impl.Constants;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.elasticsearch.ElasticSearchIllegalArgumentException;
|
||||
import org.elasticsearch.common.trove.ExtTHashMap;
|
||||
|
||||
import com.google.common.collect.ForwardingMap;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This class provides factory methods for Maps. The returned {@link Map}
|
||||
|
@ -89,4 +88,12 @@ public final class XMaps {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the given map into a read only implementation.
|
||||
*/
|
||||
public static <K, V> Map<K, V> makeReadOnly(Map<K, V> map) {
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
package org.elasticsearch.index.aliases;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.UnmodifiableIterator;
|
||||
import org.apache.lucene.queries.FilterClause;
|
||||
import org.apache.lucene.search.BooleanClause;
|
||||
import org.apache.lucene.search.Filter;
|
||||
|
@ -29,6 +27,7 @@ import org.elasticsearch.common.compress.CompressedString;
|
|||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.lucene.search.XBooleanFilter;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ConcurrentCollections;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.AbstractIndexComponent;
|
||||
|
@ -39,20 +38,16 @@ import org.elasticsearch.indices.AliasFilterParsingException;
|
|||
import org.elasticsearch.indices.InvalidAliasNameException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.common.collect.MapBuilder.newMapBuilder;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class IndexAliasesService extends AbstractIndexComponent implements Iterable<IndexAlias> {
|
||||
|
||||
private final IndexQueryParserService indexQueryParser;
|
||||
|
||||
private volatile ImmutableMap<String, IndexAlias> aliases = ImmutableMap.of();
|
||||
|
||||
private final Object mutex = new Object();
|
||||
private final Map<String, IndexAlias> aliases = ConcurrentCollections.newConcurrentMapWithAggressiveConcurrency();
|
||||
|
||||
@Inject
|
||||
public IndexAliasesService(Index index, @IndexSettings Settings indexSettings, IndexQueryParserService indexQueryParser) {
|
||||
|
@ -77,9 +72,7 @@ public class IndexAliasesService extends AbstractIndexComponent implements Itera
|
|||
}
|
||||
|
||||
public void addAll(Map<String, IndexAlias> aliases) {
|
||||
synchronized (mutex) {
|
||||
this.aliases = newMapBuilder(this.aliases).putAll(aliases).immutableMap();
|
||||
}
|
||||
this.aliases.putAll(aliases);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -126,15 +119,11 @@ public class IndexAliasesService extends AbstractIndexComponent implements Itera
|
|||
}
|
||||
|
||||
private void add(IndexAlias indexAlias) {
|
||||
synchronized (mutex) {
|
||||
aliases = newMapBuilder(aliases).put(indexAlias.alias(), indexAlias).immutableMap();
|
||||
}
|
||||
aliases.put(indexAlias.alias(), indexAlias);
|
||||
}
|
||||
|
||||
public void remove(String alias) {
|
||||
synchronized (mutex) {
|
||||
aliases = newMapBuilder(aliases).remove(alias).immutableMap();
|
||||
}
|
||||
aliases.remove(alias);
|
||||
}
|
||||
|
||||
private Filter parse(String alias, CompressedString filter) {
|
||||
|
@ -155,7 +144,7 @@ public class IndexAliasesService extends AbstractIndexComponent implements Itera
|
|||
}
|
||||
|
||||
@Override
|
||||
public UnmodifiableIterator<IndexAlias> iterator() {
|
||||
public Iterator<IndexAlias> iterator() {
|
||||
return aliases.values().iterator();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Licensed to Elastic Search and Shay Banon under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Elastic Search 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.benchmark.aliases;
|
||||
|
||||
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequestBuilder;
|
||||
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesResponse;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.indices.AliasMissingException;
|
||||
import org.elasticsearch.indices.IndexAlreadyExistsException;
|
||||
import org.elasticsearch.node.Node;
|
||||
import org.elasticsearch.node.NodeBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class AliasesBenchmark {
|
||||
|
||||
private final static String INDEX_NAME = "my-index";
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
int NUM_ADDITIONAL_NODES = 0;
|
||||
int BASE_ALIAS_COUNT = 100000;
|
||||
int NUM_ADD_ALIAS_REQUEST = 1000;
|
||||
|
||||
Settings settings = ImmutableSettings.settingsBuilder()
|
||||
.put("gateway.type", "local")
|
||||
.put("node.master", false).build();
|
||||
Node node1 = NodeBuilder.nodeBuilder().settings(
|
||||
ImmutableSettings.settingsBuilder().put(settings).put("node.master", true)
|
||||
).node();
|
||||
|
||||
Node[] otherNodes = new Node[NUM_ADDITIONAL_NODES];
|
||||
for (int i = 0; i < otherNodes.length; i++) {
|
||||
otherNodes[i] = NodeBuilder.nodeBuilder().settings(settings).node();
|
||||
}
|
||||
|
||||
Client client = node1.client();
|
||||
try {
|
||||
client.admin().indices().prepareCreate(INDEX_NAME).execute().actionGet();
|
||||
} catch (IndexAlreadyExistsException e) {}
|
||||
client.admin().cluster().prepareHealth().setWaitForYellowStatus().execute().actionGet();
|
||||
int numberOfAliases = countAliases(client);
|
||||
System.out.println("Number of aliases: " + numberOfAliases);
|
||||
|
||||
if (numberOfAliases < BASE_ALIAS_COUNT) {
|
||||
int diff = BASE_ALIAS_COUNT - numberOfAliases;
|
||||
System.out.println("Adding " + diff + " more aliases to get to the start amount of " + BASE_ALIAS_COUNT + " aliases");
|
||||
IndicesAliasesRequestBuilder builder = client.admin().indices().prepareAliases();
|
||||
for (int i = 1; i <= diff; i++) {
|
||||
builder.addAlias(INDEX_NAME, "alias" + numberOfAliases + i);
|
||||
if (i % 1000 == 0) {
|
||||
builder.execute().actionGet();
|
||||
builder = client.admin().indices().prepareAliases();
|
||||
}
|
||||
}
|
||||
if (!builder.request().getAliasActions().isEmpty()) {
|
||||
builder.execute().actionGet();
|
||||
}
|
||||
} else if (numberOfAliases > BASE_ALIAS_COUNT) {
|
||||
IndicesAliasesRequestBuilder builder = client.admin().indices().prepareAliases();
|
||||
int diff = numberOfAliases - BASE_ALIAS_COUNT;
|
||||
System.out.println("Removing " + diff + " aliases to get to the start amount of " + BASE_ALIAS_COUNT + "aliases");
|
||||
for (int i = 0; i <= diff; i++) {
|
||||
builder.removeAlias(INDEX_NAME, "alias" + (BASE_ALIAS_COUNT + i));
|
||||
if (i % 1000 == 0) {
|
||||
builder.execute().actionGet();
|
||||
builder = client.admin().indices().prepareAliases();
|
||||
}
|
||||
}
|
||||
if (!builder.request().getAliasActions().isEmpty()) {
|
||||
builder.execute().actionGet();
|
||||
}
|
||||
}
|
||||
|
||||
numberOfAliases = countAliases(client);
|
||||
System.out.println("Number of aliases: " + numberOfAliases);
|
||||
|
||||
long totalTime = 0;
|
||||
int max = numberOfAliases + NUM_ADD_ALIAS_REQUEST;
|
||||
for (int i = numberOfAliases; i <= max; i++) {
|
||||
if (i != numberOfAliases && i % 100 == 0) {
|
||||
long avgTime = totalTime / 100;
|
||||
System.out.println("Added [" + (i - numberOfAliases) + "] aliases. Avg create time: " + avgTime + " ms");
|
||||
totalTime = 0;
|
||||
}
|
||||
|
||||
long time = System.currentTimeMillis();
|
||||
// String filter = termFilter("field" + i, "value" + i).toXContent(XContentFactory.jsonBuilder(), null).string();
|
||||
client.admin().indices().prepareAliases().addAlias(INDEX_NAME, "alias" + i/*, filter*/)
|
||||
.execute().actionGet();
|
||||
totalTime += System.currentTimeMillis() - time;
|
||||
}
|
||||
System.out.println("Number of aliases: " + countAliases(client));
|
||||
|
||||
client.close();
|
||||
node1.close();
|
||||
for (Node otherNode : otherNodes) {
|
||||
otherNode.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static int countAliases(Client client) {
|
||||
try {
|
||||
GetAliasesResponse response = client.admin().indices().prepareGetAliases("a*")
|
||||
.addIndices(INDEX_NAME)
|
||||
.execute().actionGet();
|
||||
return response.getAliases().get(INDEX_NAME).size();
|
||||
} catch (AliasMissingException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue