Core: `ignore_unavailable` shouldn't ignore closed indices if a single index is specified in a search or broadcast request.

Closes #9047
Closes #7153
This commit is contained in:
Martijn van Groningen 2014-12-23 14:47:13 +01:00
parent 7678ab5264
commit a345e98575
3 changed files with 180 additions and 20 deletions

View File

@ -23,15 +23,13 @@ import org.elasticsearch.action.ActionListener;
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 @@ public class TransportSearchAction extends HandledTransportAction<SearchRequest,
// 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);
}

View File

@ -679,7 +679,7 @@ public class MetaData implements Iterable<IndexMetaData> {
// 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
@ -712,7 +712,7 @@ public class MetaData implements Iterable<IndexMetaData> {
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);
}
@ -723,16 +723,15 @@ public class MetaData implements Iterable<IndexMetaData> {
}
/**
*
* 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 class MetaData implements Iterable<IndexMetaData> {
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 @@ public class MetaData implements Iterable<IndexMetaData> {
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 class MetaData implements Iterable<IndexMetaData> {
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();

View File

@ -68,7 +68,7 @@ import static org.hamcrest.Matchers.*;
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 class IndicesOptionsIntegrationTests extends ElasticsearchIntegrationTest
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");