From a345e98575c92fef64023026581eb6b37b7720a5 Mon Sep 17 00:00:00 2001 From: Martijn van Groningen Date: Tue, 23 Dec 2014 14:47:13 +0100 Subject: [PATCH] Core: `ignore_unavailable` shouldn't ignore closed indices if a single index is specified in a search or broadcast request. Closes #9047 Closes #7153 --- .../action/search/TransportSearchAction.java | 9 +- .../cluster/metadata/MetaData.java | 37 +++-- .../IndicesOptionsIntegrationTests.java | 154 +++++++++++++++++- 3 files changed, 180 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/elasticsearch/action/search/TransportSearchAction.java b/src/main/java/org/elasticsearch/action/search/TransportSearchAction.java index 40b3584c98603..27db968e83545 100644 --- a/src/main/java/org/elasticsearch/action/search/TransportSearchAction.java +++ b/src/main/java/org/elasticsearch/action/search/TransportSearchAction.java @@ -23,15 +23,13 @@ import org.elasticsearch.action.search.type.*; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.HandledTransportAction; -import org.elasticsearch.action.support.TransportAction; import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.indices.IndexClosedException; import org.elasticsearch.indices.IndexMissingException; import org.elasticsearch.threadpool.ThreadPool; -import org.elasticsearch.transport.BaseTransportRequestHandler; -import org.elasticsearch.transport.TransportChannel; import org.elasticsearch.transport.TransportService; import java.util.Map; @@ -89,9 +87,8 @@ protected void doExecute(SearchRequest searchRequest, ActionListener actualIndices = new HashSet<>(); for (String aliasOrIndex : aliasesOrIndices) { - String[] indices = concreteIndices(aliasOrIndex, indicesOptions.ignoreUnavailable(), failClosed, indicesOptions.allowAliasesToMultipleIndices()); + String[] indices = concreteIndices(aliasOrIndex, indicesOptions.ignoreUnavailable(), indicesOptions); Collections.addAll(actualIndices, indices); } @@ -723,16 +723,15 @@ public String[] concreteIndices(IndicesOptions indicesOptions, String... aliases } /** - * * Utility method that allows to resolve an index or alias to its corresponding single concrete index. * Callers should make sure they provide proper {@link org.elasticsearch.action.support.IndicesOptions} * that require a single index as a result. The indices resolution must in fact return a single index when * using this method, an {@link org.elasticsearch.ElasticsearchIllegalArgumentException} gets thrown otherwise. * - * @param indexOrAlias the index or alias to be resolved to concrete index + * @param indexOrAlias the index or alias to be resolved to concrete index * @param indicesOptions the indices options to be used for the index resolution * @return the concrete index obtained as a result of the index resolution - * @throws IndexMissingException if the index or alias provided doesn't exist + * @throws IndexMissingException if the index or alias provided doesn't exist * @throws ElasticsearchIllegalArgumentException if the index resolution lead to more than one index */ public String concreteSingleIndex(String indexOrAlias, IndicesOptions indicesOptions) throws IndexMissingException, ElasticsearchIllegalArgumentException { @@ -743,14 +742,20 @@ public String concreteSingleIndex(String indexOrAlias, IndicesOptions indicesOpt return indices[0]; } - private String[] concreteIndices(String aliasOrIndex, boolean allowNoIndices, boolean failClosed, boolean allowMultipleIndices) throws IndexMissingException, ElasticsearchIllegalArgumentException { + private String[] concreteIndices(String aliasOrIndex, boolean allowNoIndices, IndicesOptions options) throws IndexMissingException, ElasticsearchIllegalArgumentException { + boolean failClosed = options.forbidClosedIndices() && !options.ignoreUnavailable(); + // a quick check, if this is an actual index, if so, return it IndexMetaData indexMetaData = indices.get(aliasOrIndex); if (indexMetaData != null) { - if (indexMetaData.getState() == IndexMetaData.State.CLOSE && failClosed) { - throw new IndexClosedException(new Index(aliasOrIndex)); + if (indexMetaData.getState() == IndexMetaData.State.CLOSE) { + if (failClosed) { + throw new IndexClosedException(new Index(aliasOrIndex)); + } else { + return options.forbidClosedIndices() ? Strings.EMPTY_ARRAY : new String[]{aliasOrIndex}; + } } else { - return new String[]{aliasOrIndex}; + return new String[]{aliasOrIndex}; } } // not an actual index, fetch from an alias @@ -758,13 +763,19 @@ private String[] concreteIndices(String aliasOrIndex, boolean allowNoIndices, bo if (indices.length == 0 && !allowNoIndices) { throw new IndexMissingException(new Index(aliasOrIndex)); } - if (indices.length > 1 && !allowMultipleIndices) { + if (indices.length > 1 && !options.allowAliasesToMultipleIndices()) { throw new ElasticsearchIllegalArgumentException("Alias [" + aliasOrIndex + "] has more than one indices associated with it [" + Arrays.toString(indices) + "], can't execute a single index op"); } indexMetaData = this.indices.get(aliasOrIndex); - if (indexMetaData != null && indexMetaData.getState() == IndexMetaData.State.CLOSE && failClosed) { - throw new IndexClosedException(new Index(aliasOrIndex)); + if (indexMetaData != null && indexMetaData.getState() == IndexMetaData.State.CLOSE) { + if (failClosed) { + throw new IndexClosedException(new Index(aliasOrIndex)); + } else { + if (options.forbidClosedIndices()) { + return Strings.EMPTY_ARRAY; + } + } } return indices; } @@ -1317,7 +1328,7 @@ public static void toXContent(MetaData metaData, XContentBuilder builder, ToXCon for (ObjectObjectCursor cursor : metaData.customs()) { Custom.Factory factory = lookupFactorySafe(cursor.key); - if(factory.context().contains(context)) { + if (factory.context().contains(context)) { builder.startObject(cursor.key); factory.toXContent(cursor.value, builder, params); builder.endObject(); diff --git a/src/test/java/org/elasticsearch/indices/IndicesOptionsIntegrationTests.java b/src/test/java/org/elasticsearch/indices/IndicesOptionsIntegrationTests.java index 4955cdf387307..6b5cb0bb2e971 100644 --- a/src/test/java/org/elasticsearch/indices/IndicesOptionsIntegrationTests.java +++ b/src/test/java/org/elasticsearch/indices/IndicesOptionsIntegrationTests.java @@ -68,7 +68,7 @@ public class IndicesOptionsIntegrationTests extends ElasticsearchIntegrationTest { @Test - public void testSpecifiedIndexUnavailable() throws Exception { + public void testSpecifiedIndexUnavailable_multipleIndices() throws Exception { createIndex("test1"); ensureYellow(); @@ -167,6 +167,158 @@ public void testSpecifiedIndexUnavailable() throws Exception { verify(getSettings("test1", "test2").setIndicesOptions(options), false); } + @Test + public void testSpecifiedIndexUnavailable_singleIndexThatIsClosed() throws Exception { + assertAcked(prepareCreate("test1")); + ensureYellow(); + + assertAcked(client().admin().indices().prepareClose("test1")); + + IndicesOptions options = IndicesOptions.strictExpandOpenAndForbidClosed(); + verify(search("test1").setIndicesOptions(options), true); + verify(msearch(options, "test1"), true); + verify(count("test1").setIndicesOptions(options), true); + verify(clearCache("test1").setIndicesOptions(options), true); + verify(_flush("test1").setIndicesOptions(options),true); + verify(segments("test1").setIndicesOptions(options), true); + verify(stats("test1").setIndicesOptions(options), true); + verify(optimize("test1").setIndicesOptions(options), true); + verify(refresh("test1").setIndicesOptions(options), true); + verify(validateQuery("test1").setIndicesOptions(options), true); + verify(aliasExists("test1").setIndicesOptions(options), true); + verify(typesExists("test1").setIndicesOptions(options), true); + verify(deleteByQuery("test1").setIndicesOptions(options), true); + verify(percolate("test1").setIndicesOptions(options), true); + verify(mpercolate(options, "test1").setIndicesOptions(options), true); + verify(suggest("test1").setIndicesOptions(options), true); + verify(getAliases("test1").setIndicesOptions(options), true); + verify(getFieldMapping("test1").setIndicesOptions(options), true); + verify(getMapping("test1").setIndicesOptions(options), true); + verify(getWarmer("test1").setIndicesOptions(options), true); + verify(getSettings("test1").setIndicesOptions(options), true); + + options = IndicesOptions.fromOptions(true, options.allowNoIndices(), options.expandWildcardsOpen(), options.expandWildcardsClosed(), options); + verify(search("test1").setIndicesOptions(options), false); + verify(msearch(options, "test1"), false); + verify(count("test1").setIndicesOptions(options), false); + verify(clearCache("test1").setIndicesOptions(options), false); + verify(_flush("test1").setIndicesOptions(options),false); + verify(segments("test1").setIndicesOptions(options), false); + verify(stats("test1").setIndicesOptions(options), false); + verify(optimize("test1").setIndicesOptions(options), false); + verify(refresh("test1").setIndicesOptions(options), false); + verify(validateQuery("test1").setIndicesOptions(options), false); + verify(aliasExists("test1").setIndicesOptions(options), false); + verify(typesExists("test1").setIndicesOptions(options), false); + verify(deleteByQuery("test1").setIndicesOptions(options), false); + verify(percolate("test1").setIndicesOptions(options), false); + verify(mpercolate(options, "test1").setIndicesOptions(options), false); + verify(suggest("test1").setIndicesOptions(options), false); + verify(getAliases("test1").setIndicesOptions(options), false); + verify(getFieldMapping("test1").setIndicesOptions(options), false); + verify(getMapping("test1").setIndicesOptions(options), false); + verify(getWarmer("test1").setIndicesOptions(options), false); + verify(getSettings("test1").setIndicesOptions(options), false); + + assertAcked(client().admin().indices().prepareOpen("test1")); + ensureYellow(); + + options = IndicesOptions.strictExpandOpenAndForbidClosed(); + verify(search("test1").setIndicesOptions(options), false); + verify(msearch(options, "test1"), false); + verify(count("test1").setIndicesOptions(options), false); + verify(clearCache("test1").setIndicesOptions(options), false); + verify(_flush("test1").setIndicesOptions(options),false); + verify(segments("test1").setIndicesOptions(options), false); + verify(stats("test1").setIndicesOptions(options), false); + verify(optimize("test1").setIndicesOptions(options), false); + verify(refresh("test1").setIndicesOptions(options), false); + verify(validateQuery("test1").setIndicesOptions(options), false); + verify(aliasExists("test1").setIndicesOptions(options), false); + verify(typesExists("test1").setIndicesOptions(options), false); + verify(deleteByQuery("test1").setIndicesOptions(options), false); + verify(percolate("test1").setIndicesOptions(options), false); + verify(mpercolate(options, "test1").setIndicesOptions(options), false); + verify(suggest("test1").setIndicesOptions(options), false); + verify(getAliases("test1").setIndicesOptions(options), false); + verify(getFieldMapping("test1").setIndicesOptions(options), false); + verify(getMapping("test1").setIndicesOptions(options), false); + verify(getWarmer("test1").setIndicesOptions(options), false); + verify(getSettings("test1").setIndicesOptions(options), false); + } + + @Test + public void testSpecifiedIndexUnavailable_singleIndex() throws Exception { + IndicesOptions options = IndicesOptions.strictExpandOpenAndForbidClosed(); + verify(search("test1").setIndicesOptions(options), true); + verify(msearch(options, "test1"), true); + verify(count("test1").setIndicesOptions(options), true); + verify(clearCache("test1").setIndicesOptions(options), true); + verify(_flush("test1").setIndicesOptions(options),true); + verify(segments("test1").setIndicesOptions(options), true); + verify(stats("test1").setIndicesOptions(options), true); + verify(optimize("test1").setIndicesOptions(options), true); + verify(refresh("test1").setIndicesOptions(options), true); + verify(validateQuery("test1").setIndicesOptions(options), true); + verify(aliasExists("test1").setIndicesOptions(options), true); + verify(typesExists("test1").setIndicesOptions(options), true); + verify(deleteByQuery("test1").setIndicesOptions(options), true); + verify(percolate("test1").setIndicesOptions(options), true); + verify(suggest("test1").setIndicesOptions(options), true); + verify(getAliases("test1").setIndicesOptions(options), true); + verify(getFieldMapping("test1").setIndicesOptions(options), true); + verify(getMapping("test1").setIndicesOptions(options), true); + verify(getWarmer("test1").setIndicesOptions(options), true); + verify(getSettings("test1").setIndicesOptions(options), true); + + options = IndicesOptions.fromOptions(true, options.allowNoIndices(), options.expandWildcardsOpen(), options.expandWildcardsClosed(), options); + verify(search("test1").setIndicesOptions(options), false); + verify(msearch(options, "test1"), false); + verify(count("test1").setIndicesOptions(options), false); + verify(clearCache("test1").setIndicesOptions(options), false); + verify(_flush("test1").setIndicesOptions(options),false); + verify(segments("test1").setIndicesOptions(options), false); + verify(stats("test1").setIndicesOptions(options), false); + verify(optimize("test1").setIndicesOptions(options), false); + verify(refresh("test1").setIndicesOptions(options), false); + verify(validateQuery("test1").setIndicesOptions(options), false); + verify(aliasExists("test1").setIndicesOptions(options), false); + verify(typesExists("test1").setIndicesOptions(options), false); + verify(deleteByQuery("test1").setIndicesOptions(options), false); + verify(percolate("test1").setIndicesOptions(options), false); + verify(suggest("test1").setIndicesOptions(options), false); + verify(getAliases("test1").setIndicesOptions(options), false); + verify(getFieldMapping("test1").setIndicesOptions(options), false); + verify(getMapping("test1").setIndicesOptions(options), false); + verify(getWarmer("test1").setIndicesOptions(options), false); + verify(getSettings("test1").setIndicesOptions(options), false); + + assertAcked(prepareCreate("test1")); + ensureYellow(); + + options = IndicesOptions.strictExpandOpenAndForbidClosed(); + verify(search("test1").setIndicesOptions(options), false); + verify(msearch(options, "test1"), false); + verify(count("test1").setIndicesOptions(options), false); + verify(clearCache("test1").setIndicesOptions(options), false); + verify(_flush("test1").setIndicesOptions(options),false); + verify(segments("test1").setIndicesOptions(options), false); + verify(stats("test1").setIndicesOptions(options), false); + verify(optimize("test1").setIndicesOptions(options), false); + verify(refresh("test1").setIndicesOptions(options), false); + verify(validateQuery("test1").setIndicesOptions(options), false); + verify(aliasExists("test1").setIndicesOptions(options), false); + verify(typesExists("test1").setIndicesOptions(options), false); + verify(deleteByQuery("test1").setIndicesOptions(options), false); + verify(percolate("test1").setIndicesOptions(options), false); + verify(suggest("test1").setIndicesOptions(options), false); + verify(getAliases("test1").setIndicesOptions(options), false); + verify(getFieldMapping("test1").setIndicesOptions(options), false); + verify(getMapping("test1").setIndicesOptions(options), false); + verify(getWarmer("test1").setIndicesOptions(options), false); + verify(getSettings("test1").setIndicesOptions(options), false); + } + @Test public void testSpecifiedIndexUnavailable_snapshotRestore() throws Exception { createIndex("test1");