From b4b92a8e7f14aa85fbc272a30da412ce65172ecc Mon Sep 17 00:00:00 2001 From: Igor Motov Date: Tue, 17 May 2011 14:12:49 -0400 Subject: [PATCH] Move alias metadata from settings to a separate data structure --- .../cluster/metadata/AliasMetaData.java | 98 +++++++++++++++++++ .../cluster/metadata/IndexMetaData.java | 66 +++++++++++-- .../cluster/metadata/MetaData.java | 4 +- .../metadata/MetaDataIndexAliasesService.java | 16 +-- .../cluster/state/RestClusterStateAction.java | 2 +- .../metadata/ToAndFromJsonMetaDataTests.java | 48 +++++++++ 6 files changed, 213 insertions(+), 21 deletions(-) create mode 100644 modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/AliasMetaData.java diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/AliasMetaData.java b/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/AliasMetaData.java new file mode 100644 index 00000000000..056f5c78437 --- /dev/null +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/AliasMetaData.java @@ -0,0 +1,98 @@ +/* + * 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.cluster.metadata; + +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.util.concurrent.Immutable; +import org.elasticsearch.common.xcontent.*; + +import java.io.IOException; + +/** + * @author imotov + */ +@Immutable +public class AliasMetaData { + + private final String alias; + + private AliasMetaData(String alias) { + this.alias = alias; + } + + public String alias() { + return alias; + } + + public String getAlias() { + return alias(); + } + + public static Builder newAliasMetaDataBuilder(String alias) { + return new Builder(alias); + } + + public static class Builder { + + private String alias; + + public Builder(String alias) { + this.alias = alias; + } + + public Builder(AliasMetaData aliasMetaData) { + this(aliasMetaData.alias()); + } + + public String alias() { + return alias; + } + + public AliasMetaData build() { + return new AliasMetaData(alias); + } + + public static void toXContent(AliasMetaData aliasMetaData, XContentBuilder builder, ToXContent.Params params) throws IOException { + builder.startObject(aliasMetaData.alias(), XContentBuilder.FieldCaseConversion.NONE); + // Filters will go here + builder.endObject(); + } + + public static AliasMetaData fromXContent(XContentParser parser) throws IOException { + Builder builder = new Builder(parser.currentName()); + XContentParser.Token token = parser.nextToken(); + while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { + // Skip the content for now, filter and other settings will go here + } + return builder.build(); + } + + public static void writeTo(AliasMetaData aliasMetaData, StreamOutput out) throws IOException { + out.writeUTF(aliasMetaData.alias()); + } + + public static AliasMetaData readFrom(StreamInput in) throws IOException { + String alias = in.readUTF(); + return new AliasMetaData(alias); + } + } + +} diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java b/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java index 65d73122c18..39baf35e0b1 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java @@ -88,7 +88,7 @@ public class IndexMetaData { private final State state; - private final ImmutableSet aliases; + private final ImmutableMap aliases; private final Settings settings; @@ -96,7 +96,7 @@ public class IndexMetaData { private transient final int totalNumberOfShards; - private IndexMetaData(String index, State state, Settings settings, ImmutableMap mappings) { + private IndexMetaData(String index, State state, Settings settings, ImmutableMap mappings, ImmutableMap aliases) { 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; @@ -105,7 +105,7 @@ public class IndexMetaData { this.mappings = mappings; this.totalNumberOfShards = numberOfShards() * (numberOfReplicas() + 1); - this.aliases = ImmutableSet.copyOf(settings.getAsArray("index.aliases")); + this.aliases = aliases; } public String index() { @@ -156,11 +156,11 @@ public class IndexMetaData { return settings(); } - public ImmutableSet aliases() { + public ImmutableMap aliases() { return this.aliases; } - public ImmutableSet getAliases() { + public ImmutableMap getAliases() { return aliases(); } @@ -194,6 +194,8 @@ public class IndexMetaData { private MapBuilder mappings = MapBuilder.newMapBuilder(); + private MapBuilder aliases = MapBuilder.newMapBuilder(); + public Builder(String index) { this.index = index; } @@ -202,6 +204,7 @@ public class IndexMetaData { this(indexMetaData.index()); settings(indexMetaData.settings()); mappings.putAll(indexMetaData.mappings); + aliases.putAll(indexMetaData.aliases); this.state = indexMetaData.state; } @@ -262,8 +265,39 @@ public class IndexMetaData { return this; } + public Builder putAlias(AliasMetaData aliasMetaData) { + aliases.put(aliasMetaData.alias(), aliasMetaData); + return this; + } + + public Builder putAlias(AliasMetaData.Builder aliasMetaData) { + aliases.put(aliasMetaData.alias(), aliasMetaData.build()); + return this; + } + + public Builder removerAlias(String alias) { + aliases.remove(alias); + return this; + } + public IndexMetaData build() { - return new IndexMetaData(index, state, settings, mappings.immutableMap()); + MapBuilder tmpAliases = aliases; + Settings tmpSettings = settings; + + // For backward compatibility + String[] legacyAliases = settings.getAsArray("index.aliases"); + if (legacyAliases.length > 0) { + tmpAliases = MapBuilder.newMapBuilder(); + for (String alias : legacyAliases) { + AliasMetaData aliasMd = AliasMetaData.newAliasMetaDataBuilder(alias).build(); + tmpAliases.put(alias, aliasMd); + } + tmpAliases.putAll(aliases.immutableMap()); + // Remove index.aliases from settings once they are migrated to the new data structure + tmpSettings = ImmutableSettings.settingsBuilder().put(settings).putArray("index.aliases").build(); + } + + return new IndexMetaData(index, state, tmpSettings, mappings.immutableMap(), tmpAliases.immutableMap()); } public static void toXContent(IndexMetaData indexMetaData, XContentBuilder builder, ToXContent.Params params) throws IOException { @@ -287,6 +321,13 @@ public class IndexMetaData { } builder.endArray(); + builder.startObject("aliases"); + for (AliasMetaData alias : indexMetaData.aliases().values()) { + AliasMetaData.Builder.toXContent(alias, builder, params); + } + builder.endObject(); + + builder.endObject(); } @@ -316,6 +357,10 @@ public class IndexMetaData { builder.putMapping(new MappingMetaData(mappingType, mapping)); } } + } else if ("aliases".equals(currentFieldName)) { + while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { + builder.putAlias(AliasMetaData.Builder.fromXContent(parser)); + } } } else if (token.isValue()) { if ("state".equals(currentFieldName)) { @@ -335,6 +380,11 @@ public class IndexMetaData { MappingMetaData mappingMd = MappingMetaData.readFrom(in); builder.putMapping(mappingMd); } + int aliasesSize = in.readVInt(); + for (int i = 0; i < aliasesSize; i++) { + AliasMetaData aliasMd = AliasMetaData.Builder.readFrom(in); + builder.putAlias(aliasMd); + } return builder.build(); } @@ -346,6 +396,10 @@ public class IndexMetaData { for (MappingMetaData mappingMd : indexMetaData.mappings().values()) { MappingMetaData.writeTo(mappingMd, out); } + out.writeVInt(indexMetaData.aliases().size()); + for (AliasMetaData aliasMd : indexMetaData.aliases().values()) { + AliasMetaData.Builder.writeTo(aliasMd, out); + } } } } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java b/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java index 6f58b1a002f..1b9a367d5bd 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java @@ -75,7 +75,7 @@ public class MetaData implements Iterable { // build aliases set Set aliases = newHashSet(); for (IndexMetaData indexMetaData : indices.values()) { - aliases.addAll(indexMetaData.aliases()); + aliases.addAll(indexMetaData.aliases().keySet()); } this.aliases = ImmutableSet.copyOf(aliases); @@ -89,7 +89,7 @@ public class MetaData implements Iterable { } lst.add(indexMetaData.index()); - for (String alias : indexMetaData.aliases()) { + for (String alias : indexMetaData.aliases().keySet()) { lst = tmpAliasAndIndexToIndexBuilder.get(alias); if (lst == null) { lst = newHashSet(); diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesService.java b/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesService.java index 63c293e13c9..783ae84c92c 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesService.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesService.java @@ -29,13 +29,9 @@ import org.elasticsearch.index.Index; import org.elasticsearch.indices.IndexMissingException; import org.elasticsearch.indices.InvalidAliasNameException; -import java.util.Set; - import static org.elasticsearch.cluster.ClusterState.*; import static org.elasticsearch.cluster.metadata.IndexMetaData.*; import static org.elasticsearch.cluster.metadata.MetaData.*; -import static org.elasticsearch.common.collect.Sets.*; -import static org.elasticsearch.common.settings.ImmutableSettings.*; /** * @author kimchy (shay.banon) @@ -70,18 +66,14 @@ public class MetaDataIndexAliasesService extends AbstractComponent { if (indexMetaData == null) { throw new IndexMissingException(new Index(aliasAction.index())); } - Set indexAliases = newHashSet(indexMetaData.settings().getAsArray("index.aliases")); + IndexMetaData.Builder indexMetaDataBuilder = newIndexMetaDataBuilder(indexMetaData); if (aliasAction.actionType() == AliasAction.Type.ADD) { - indexAliases.add(aliasAction.alias()); + indexMetaDataBuilder.putAlias(AliasMetaData.newAliasMetaDataBuilder(aliasAction.alias()).build()); } else if (aliasAction.actionType() == AliasAction.Type.REMOVE) { - indexAliases.remove(aliasAction.alias()); + indexMetaDataBuilder.removerAlias(aliasAction.alias()); } - Settings settings = settingsBuilder().put(indexMetaData.settings()) - .putArray("index.aliases", indexAliases.toArray(new String[indexAliases.size()])) - .build(); - - builder.put(newIndexMetaDataBuilder(indexMetaData).settings(settings)); + builder.put(indexMetaDataBuilder); } return newClusterStateBuilder().state(currentState).metaData(builder).build(); } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/admin/cluster/state/RestClusterStateAction.java b/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/admin/cluster/state/RestClusterStateAction.java index 6bd4d2bed03..95bd6a5b503 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/admin/cluster/state/RestClusterStateAction.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/rest/action/admin/cluster/state/RestClusterStateAction.java @@ -201,7 +201,7 @@ public class RestClusterStateAction extends BaseRestHandler { builder.endObject(); builder.startArray("aliases"); - for (String alias : indexMetaData.aliases()) { + for (String alias : indexMetaData.aliases().keySet()) { builder.value(alias); } builder.endArray(); diff --git a/modules/elasticsearch/src/test/java/org/elasticsearch/cluster/metadata/ToAndFromJsonMetaDataTests.java b/modules/elasticsearch/src/test/java/org/elasticsearch/cluster/metadata/ToAndFromJsonMetaDataTests.java index 25f32172536..3b710b8e7d3 100644 --- a/modules/elasticsearch/src/test/java/org/elasticsearch/cluster/metadata/ToAndFromJsonMetaDataTests.java +++ b/modules/elasticsearch/src/test/java/org/elasticsearch/cluster/metadata/ToAndFromJsonMetaDataTests.java @@ -25,6 +25,7 @@ import org.testng.annotations.Test; import java.io.IOException; +import static org.elasticsearch.cluster.metadata.AliasMetaData.newAliasMetaDataBuilder; import static org.elasticsearch.cluster.metadata.IndexMetaData.*; import static org.elasticsearch.cluster.metadata.MetaData.*; import static org.elasticsearch.common.settings.ImmutableSettings.*; @@ -57,6 +58,26 @@ public class ToAndFromJsonMetaDataTests { .numberOfReplicas(2) .putMapping("mapping1", MAPPING_SOURCE1) .putMapping("mapping2", MAPPING_SOURCE2)) + .put(newIndexMetaDataBuilder("test5") + .settings(settingsBuilder().put("setting1", "value1").put("setting2", "value2")) + .numberOfShards(1) + .numberOfReplicas(2) + .putMapping("mapping1", MAPPING_SOURCE1) + .putMapping("mapping2", MAPPING_SOURCE2) + .putAlias(newAliasMetaDataBuilder("alias1")) + .putAlias(newAliasMetaDataBuilder("alias2"))) + .put(newIndexMetaDataBuilder("test6") + .settings(settingsBuilder() + .put("setting1", "value1") + .put("setting2", "value2") + .put("index.aliases.0", "alias3") + .put("index.aliases.1", "alias1")) + .numberOfShards(1) + .numberOfReplicas(2) + .putMapping("mapping1", MAPPING_SOURCE1) + .putMapping("mapping2", MAPPING_SOURCE2) + .putAlias(newAliasMetaDataBuilder("alias1")) + .putAlias(newAliasMetaDataBuilder("alias2"))) .build(); String metaDataSource = MetaData.Builder.toXContent(metaData); @@ -94,6 +115,33 @@ public class ToAndFromJsonMetaDataTests { assertThat(indexMetaData.mappings().size(), equalTo(2)); assertThat(indexMetaData.mappings().get("mapping1").source().string(), equalTo(MAPPING_SOURCE1)); assertThat(indexMetaData.mappings().get("mapping2").source().string(), equalTo(MAPPING_SOURCE2)); + + indexMetaData = parsedMetaData.index("test5"); + assertThat(indexMetaData.numberOfShards(), equalTo(1)); + assertThat(indexMetaData.numberOfReplicas(), equalTo(2)); + assertThat(indexMetaData.settings().getAsMap().size(), equalTo(4)); + assertThat(indexMetaData.settings().get("setting1"), equalTo("value1")); + assertThat(indexMetaData.settings().get("setting2"), equalTo("value2")); + assertThat(indexMetaData.mappings().size(), equalTo(2)); + assertThat(indexMetaData.mappings().get("mapping1").source().string(), equalTo(MAPPING_SOURCE1)); + assertThat(indexMetaData.mappings().get("mapping2").source().string(), equalTo(MAPPING_SOURCE2)); + assertThat(indexMetaData.aliases().size(), equalTo(2)); + assertThat(indexMetaData.aliases().get("alias1").alias(), equalTo("alias1")); + assertThat(indexMetaData.aliases().get("alias2").alias(), equalTo("alias2")); + + indexMetaData = parsedMetaData.index("test6"); + assertThat(indexMetaData.numberOfShards(), equalTo(1)); + assertThat(indexMetaData.numberOfReplicas(), equalTo(2)); + assertThat(indexMetaData.settings().getAsMap().size(), equalTo(4)); + assertThat(indexMetaData.settings().get("setting1"), equalTo("value1")); + assertThat(indexMetaData.settings().get("setting2"), equalTo("value2")); + assertThat(indexMetaData.mappings().size(), equalTo(2)); + assertThat(indexMetaData.mappings().get("mapping1").source().string(), equalTo(MAPPING_SOURCE1)); + assertThat(indexMetaData.mappings().get("mapping2").source().string(), equalTo(MAPPING_SOURCE2)); + assertThat(indexMetaData.aliases().size(), equalTo(3)); + assertThat(indexMetaData.aliases().get("alias1").alias(), equalTo("alias1")); + assertThat(indexMetaData.aliases().get("alias2").alias(), equalTo("alias2")); + assertThat(indexMetaData.aliases().get("alias3").alias(), equalTo("alias3")); } private static final String MAPPING_SOURCE1 = "{\"mapping1\":{\"text1\":{\"type\":\"string\"}}}";