Skip to content

Commit

Permalink
Core: ignore_unavailable shouldn't ignore closed indices if a singl…
Browse files Browse the repository at this point in the history
…e index is specified in a search or broadcast request.

Closes elastic#9047
Closes elastic#7153
  • Loading branch information
martijnvg committed Dec 24, 2014
1 parent 7f35edc commit 01ba747
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 20 deletions.
Expand Up @@ -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;
Expand Down Expand Up @@ -89,9 +87,8 @@ protected void doExecute(SearchRequest searchRequest, ActionListener<SearchRespo
// if we only have one group, then we always want Q_A_F, no need for DFS, and no need to do THEN since we hit one shard
searchRequest.searchType(QUERY_AND_FETCH);
}
} catch (IndexMissingException e) {
// ignore this, we will notify the search response if its really the case
// from the actual action
} catch (IndexMissingException|IndexClosedException e) {
// ignore these failures, we will notify the search response if its really the case from the actual action
} catch (Exception e) {
logger.debug("failed to optimize search type, continue as normal", e);
}
Expand Down
37 changes: 24 additions & 13 deletions src/main/java/org/elasticsearch/cluster/metadata/MetaData.java
Expand Up @@ -688,7 +688,7 @@ public String[] concreteIndices(IndicesOptions indicesOptions, String... aliases

// optimize for single element index (common case)
if (aliasesOrIndices.length == 1) {
return concreteIndices(aliasesOrIndices[0], indicesOptions.allowNoIndices(), failClosed, indicesOptions.allowAliasesToMultipleIndices());
return concreteIndices(aliasesOrIndices[0], indicesOptions.allowNoIndices(), indicesOptions);
}

// check if its a possible aliased index, if not, just return the passed array
Expand Down Expand Up @@ -721,7 +721,7 @@ public String[] concreteIndices(IndicesOptions indicesOptions, String... aliases

Set<String> 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);
}

Expand All @@ -732,16 +732,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 {
Expand All @@ -752,28 +751,40 @@ 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
String[] indices = aliasAndIndexToIndexMap.getOrDefault(aliasOrIndex, Strings.EMPTY_ARRAY);
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;
}
Expand Down Expand Up @@ -1326,7 +1337,7 @@ public static void toXContent(MetaData metaData, XContentBuilder builder, ToXCon

for (ObjectObjectCursor<String, Custom> 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();
Expand Down
Expand Up @@ -69,7 +69,7 @@
public class IndicesOptionsIntegrationTests extends ElasticsearchIntegrationTest {

@Test
public void testSpecifiedIndexUnavailable() throws Exception {
public void testSpecifiedIndexUnavailable_multipleIndices() throws Exception {
createIndex("test1");
ensureYellow();

Expand Down Expand Up @@ -172,6 +172,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");
Expand Down

0 comments on commit 01ba747

Please sign in to comment.