From f022a5376ba5565cc3fafc8582a1bb6ac5682fff Mon Sep 17 00:00:00 2001 From: Ievgen Degtiarenko Date: Fri, 1 Nov 2024 10:44:49 +0100 Subject: [PATCH] Prevent multiple sets copies while adding index aliases (#115934) (#116067) --- .../cluster/metadata/Metadata.java | 85 +++---------------- 1 file changed, 14 insertions(+), 71 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/Metadata.java b/server/src/main/java/org/elasticsearch/cluster/metadata/Metadata.java index 905c3078b3c9c..8a1537ed10e3f 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/Metadata.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/Metadata.java @@ -1803,7 +1803,6 @@ public static class Builder { private DiffableStringMap hashesOfConsistentSettings = DiffableStringMap.EMPTY; private final ImmutableOpenMap.Builder indices; - private final ImmutableOpenMap.Builder> aliasedIndices; private final ImmutableOpenMap.Builder templates; private final ImmutableOpenMap.Builder customs; @@ -1833,7 +1832,6 @@ public Builder() { this.hashesOfConsistentSettings = metadata.hashesOfConsistentSettings; this.version = metadata.version; this.indices = ImmutableOpenMap.builder(metadata.indices); - this.aliasedIndices = ImmutableOpenMap.builder(metadata.aliasedIndices); this.templates = ImmutableOpenMap.builder(metadata.templates); this.customs = ImmutableOpenMap.builder(metadata.customs); this.previousIndicesLookup = metadata.indicesLookup; @@ -1846,7 +1844,6 @@ public Builder() { private Builder(Map mappingsByHash, int indexCountHint) { clusterUUID = UNKNOWN_CLUSTER_UUID; indices = ImmutableOpenMap.builder(indexCountHint); - aliasedIndices = ImmutableOpenMap.builder(); templates = ImmutableOpenMap.builder(); customs = ImmutableOpenMap.builder(); reservedStateMetadata = new HashMap<>(); @@ -1861,7 +1858,6 @@ public Builder put(IndexMetadata.Builder indexMetadataBuilder) { dedupeMapping(indexMetadataBuilder); IndexMetadata indexMetadata = indexMetadataBuilder.build(); IndexMetadata previous = indices.put(indexMetadata.getIndex().getName(), indexMetadata); - updateAliases(previous, indexMetadata); if (unsetPreviousIndicesLookup(previous, indexMetadata)) { previousIndicesLookup = null; } @@ -1886,7 +1882,6 @@ public Builder put(IndexMetadata indexMetadata, boolean incrementVersion) { return this; } } - updateAliases(previous, indexMetadata); if (unsetPreviousIndicesLookup(previous, indexMetadata)) { previousIndicesLookup = null; } @@ -1961,8 +1956,7 @@ public IndexMetadata getSafe(Index index) { public Builder remove(String index) { previousIndicesLookup = null; checkForUnusedMappings = true; - IndexMetadata previous = indices.remove(index); - updateAliases(previous, null); + indices.remove(index); return this; } @@ -1972,7 +1966,6 @@ public Builder removeAllIndices() { indices.clear(); mappingsByHash.clear(); - aliasedIndices.clear(); return this; } @@ -1983,67 +1976,6 @@ public Builder indices(Map indices) { return this; } - void updateAliases(IndexMetadata previous, IndexMetadata current) { - if (previous == null && current != null) { - for (var key : current.getAliases().keySet()) { - putAlias(key, current.getIndex()); - } - } else if (previous != null && current == null) { - for (var key : previous.getAliases().keySet()) { - removeAlias(key, previous.getIndex()); - } - } else if (previous != null && current != null) { - if (Objects.equals(previous.getAliases(), current.getAliases())) { - return; - } - - for (var key : current.getAliases().keySet()) { - if (previous.getAliases().containsKey(key) == false) { - putAlias(key, current.getIndex()); - } - } - for (var key : previous.getAliases().keySet()) { - if (current.getAliases().containsKey(key) == false) { - removeAlias(key, current.getIndex()); - } - } - } - } - - private Builder putAlias(String alias, Index index) { - Objects.requireNonNull(alias); - Objects.requireNonNull(index); - - Set indices = new HashSet<>(aliasedIndices.getOrDefault(alias, Set.of())); - if (indices.add(index) == false) { - return this; // indices already contained this index - } - aliasedIndices.put(alias, Collections.unmodifiableSet(indices)); - return this; - } - - private Builder removeAlias(String alias, Index index) { - Objects.requireNonNull(alias); - Objects.requireNonNull(index); - - Set indices = aliasedIndices.get(alias); - if (indices == null || indices.isEmpty()) { - throw new IllegalStateException("Cannot remove non-existent alias [" + alias + "] for index [" + index.getName() + "]"); - } - - indices = new HashSet<>(indices); - if (indices.remove(index) == false) { - throw new IllegalStateException("Cannot remove non-existent alias [" + alias + "] for index [" + index.getName() + "]"); - } - - if (indices.isEmpty()) { - aliasedIndices.remove(alias); // for consistency, we don't store empty sets, so null it out - } else { - aliasedIndices.put(alias, Collections.unmodifiableSet(indices)); - } - return this; - } - public Builder put(IndexTemplateMetadata.Builder template) { return put(template.build()); } @@ -2365,6 +2297,7 @@ public Metadata build(boolean skipNameCollisionChecks) { int totalNumberOfShards = 0; int totalOpenIndexShards = 0; + ImmutableOpenMap.Builder> aliasedIndicesBuilder = ImmutableOpenMap.builder(); final String[] allIndicesArray = new String[indicesMap.size()]; int i = 0; final Set sha256HashesInUse = checkForUnusedMappings ? Sets.newHashSetWithExpectedSize(mappingsByHash.size()) : null; @@ -2396,9 +2329,19 @@ public Metadata build(boolean skipNameCollisionChecks) { sha256HashesInUse.add(mapping.getSha256()); } } + for (var alias : indexMetadata.getAliases().keySet()) { + var indices = aliasedIndicesBuilder.get(alias); + if (indices == null) { + indices = new HashSet<>(); + aliasedIndicesBuilder.put(alias, indices); + } + indices.add(indexMetadata.getIndex()); + } } - - var aliasedIndices = this.aliasedIndices.build(); + for (String alias : aliasedIndicesBuilder.keys()) { + aliasedIndicesBuilder.put(alias, Collections.unmodifiableSet(aliasedIndicesBuilder.get(alias))); + } + var aliasedIndices = aliasedIndicesBuilder.build(); for (var entry : aliasedIndices.entrySet()) { List aliasIndices = entry.getValue().stream().map(idx -> indicesMap.get(idx.getName())).toList(); validateAlias(entry.getKey(), aliasIndices);