-
Notifications
You must be signed in to change notification settings - Fork 24.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MetaData Builder doesn't properly prevent an alias with the same name as an index #26804
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,7 @@ | |
import com.carrotsearch.hppc.ObjectHashSet; | ||
import com.carrotsearch.hppc.cursors.ObjectCursor; | ||
import com.carrotsearch.hppc.cursors.ObjectObjectCursor; | ||
|
||
import joptsimple.internal.Strings; | ||
import org.apache.logging.log4j.Logger; | ||
import org.apache.lucene.util.CollectionUtil; | ||
import org.elasticsearch.cluster.Diff; | ||
|
@@ -62,9 +62,11 @@ | |
import java.util.Comparator; | ||
import java.util.EnumSet; | ||
import java.util.HashMap; | ||
import java.util.HashSet; | ||
import java.util.Iterator; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import java.util.SortedMap; | ||
import java.util.TreeMap; | ||
|
||
|
@@ -914,55 +916,69 @@ public MetaData build() { | |
// while these datastructures aren't even used. | ||
// 2) The aliasAndIndexLookup can be updated instead of rebuilding it all the time. | ||
|
||
// build all concrete indices arrays: | ||
// TODO: I think we can remove these arrays. it isn't worth the effort, for operations on all indices. | ||
// When doing an operation across all indices, most of the time is spent on actually going to all shards and | ||
// do the required operations, the bottleneck isn't resolving expressions into concrete indices. | ||
List<String> allIndicesLst = new ArrayList<>(); | ||
for (ObjectCursor<IndexMetaData> cursor : indices.values()) { | ||
allIndicesLst.add(cursor.value.getIndex().getName()); | ||
} | ||
String[] allIndices = allIndicesLst.toArray(new String[allIndicesLst.size()]); | ||
|
||
List<String> allOpenIndicesLst = new ArrayList<>(); | ||
List<String> allClosedIndicesLst = new ArrayList<>(); | ||
final Set<String> allIndices = new HashSet<>(); | ||
final List<String> allOpenIndices = new ArrayList<>(); | ||
final List<String> allClosedIndices = new ArrayList<>(); | ||
final Set<String> duplicateAliasesIndices = new HashSet<>(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can just be named There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I started that way, but since Java doesn't have a normal non set modifying set difference I had to mutate this set. I felt it's dangerous to just call it |
||
for (ObjectCursor<IndexMetaData> cursor : indices.values()) { | ||
IndexMetaData indexMetaData = cursor.value; | ||
final IndexMetaData indexMetaData = cursor.value; | ||
final String name = indexMetaData.getIndex().getName(); | ||
boolean added = allIndices.add(name); | ||
assert added : "double index named [" + name + "]"; | ||
if (indexMetaData.getState() == IndexMetaData.State.OPEN) { | ||
allOpenIndicesLst.add(indexMetaData.getIndex().getName()); | ||
allOpenIndices.add(indexMetaData.getIndex().getName()); | ||
} else if (indexMetaData.getState() == IndexMetaData.State.CLOSE) { | ||
allClosedIndicesLst.add(indexMetaData.getIndex().getName()); | ||
allClosedIndices.add(indexMetaData.getIndex().getName()); | ||
} | ||
indexMetaData.getAliases().keysIt().forEachRemaining(duplicateAliasesIndices::add); | ||
} | ||
duplicateAliasesIndices.retainAll(allIndices); | ||
if (duplicateAliasesIndices.isEmpty() == false) { | ||
// iterate again and constructs a helpful message | ||
ArrayList<String> duplicates = new ArrayList<>(); | ||
for (ObjectCursor<IndexMetaData> cursor : indices.values()) { | ||
for (String alias: duplicateAliasesIndices) { | ||
if (cursor.value.getAliases().containsKey(alias)) { | ||
duplicates.add(alias + " (alias of " + cursor.value.getIndex() + ")"); | ||
} | ||
} | ||
} | ||
assert duplicates.size() > 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps add the duplicate size to the assert message here There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's 0 ? :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. whoops I read it backwards, so yeah, not really necessary |
||
throw new IllegalStateException("index and alias names need to be unique, but the following duplicates were found [" | ||
+ Strings.join(duplicates, ", ")+ "]"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. woops. Good catch |
||
|
||
} | ||
String[] allOpenIndices = allOpenIndicesLst.toArray(new String[allOpenIndicesLst.size()]); | ||
String[] allClosedIndices = allClosedIndicesLst.toArray(new String[allClosedIndicesLst.size()]); | ||
|
||
// build all indices map | ||
SortedMap<String, AliasOrIndex> aliasAndIndexLookup = new TreeMap<>(); | ||
for (ObjectCursor<IndexMetaData> cursor : indices.values()) { | ||
IndexMetaData indexMetaData = cursor.value; | ||
aliasAndIndexLookup.put(indexMetaData.getIndex().getName(), new AliasOrIndex.Index(indexMetaData)); | ||
AliasOrIndex exiting = aliasAndIndexLookup.put(indexMetaData.getIndex().getName(), new AliasOrIndex.Index(indexMetaData)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. exiting -> exists |
||
assert exiting == null : "duplicate for " + indexMetaData.getIndex(); | ||
|
||
for (ObjectObjectCursor<String, AliasMetaData> aliasCursor : indexMetaData.getAliases()) { | ||
AliasMetaData aliasMetaData = aliasCursor.value; | ||
AliasOrIndex aliasOrIndex = aliasAndIndexLookup.get(aliasMetaData.getAlias()); | ||
if (aliasOrIndex == null) { | ||
aliasOrIndex = new AliasOrIndex.Alias(aliasMetaData, indexMetaData); | ||
aliasAndIndexLookup.put(aliasMetaData.getAlias(), aliasOrIndex); | ||
} else if (aliasOrIndex instanceof AliasOrIndex.Alias) { | ||
AliasOrIndex.Alias alias = (AliasOrIndex.Alias) aliasOrIndex; | ||
alias.addIndex(indexMetaData); | ||
} else if (aliasOrIndex instanceof AliasOrIndex.Index) { | ||
AliasOrIndex.Index index = (AliasOrIndex.Index) aliasOrIndex; | ||
throw new IllegalStateException("index and alias names need to be unique, but alias [" + aliasMetaData.getAlias() + "] and index " + index.getIndex().getIndex() + " have the same name"); | ||
AliasOrIndex alias = aliasAndIndexLookup.get(aliasMetaData.getAlias()); | ||
if (alias == null) { | ||
alias = new AliasOrIndex.Alias(aliasMetaData, indexMetaData); | ||
aliasAndIndexLookup.put(aliasMetaData.getAlias(), alias); | ||
} else { | ||
throw new IllegalStateException("unexpected alias [" + aliasMetaData.getAlias() + "][" + aliasOrIndex + "]"); | ||
assert alias instanceof AliasOrIndex.Alias : alias.getClass().getName(); | ||
((AliasOrIndex.Alias) alias).addIndex(indexMetaData); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this would be cleaner as aliasAndIndexLookup.compute(aliasMetaData.getAlias(), (aliasName, alias) -> {
if (alias == null) {
return new AliasOrIndex.Alias(aliasMetaData, indexMetaData);
} else {
((AliasOrIndex.Alias) alias).addIndex(indexMetaData);
return alias;
}
}); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure |
||
} | ||
} | ||
} | ||
aliasAndIndexLookup = Collections.unmodifiableSortedMap(aliasAndIndexLookup); | ||
// build all concrete indices arrays: | ||
// TODO: I think we can remove these arrays. it isn't worth the effort, for operations on all indices. | ||
// When doing an operation across all indices, most of the time is spent on actually going to all shards and | ||
// do the required operations, the bottleneck isn't resolving expressions into concrete indices. | ||
String[] allIndicesArray = allIndices.toArray(new String[allIndices.size()]); | ||
String[] allOpenIndicesArray = allOpenIndices.toArray(new String[allOpenIndices.size()]); | ||
String[] allClosedIndicesArray = allClosedIndices.toArray(new String[allClosedIndices.size()]); | ||
|
||
return new MetaData(clusterUUID, version, transientSettings, persistentSettings, indices.build(), templates.build(), | ||
customs.build(), allIndices, allOpenIndices, allClosedIndices, aliasAndIndexLookup); | ||
customs.build(), allIndicesArray, allOpenIndicesArray, allClosedIndicesArray, aliasAndIndexLookup); | ||
} | ||
|
||
public static String toXContent(MetaData metaData) throws IOException { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor nit, this can be
new HashSet<>(indices.size())