Skip to content

Commit c474c74

Browse files
committed
Preserve index_uuid when creating QueryShardException
As part of elastic#32608 we made sure that the fully qualified index name is taken from the query shard context whenever creating a new `QueryShardException`. That change introduced a regression as instead of setting the entire `Index` object to the exception, which holds index name and index uuid, we ended up setting only the index name (including cluster alias). With this commit we make sure that the index uuid does not get lost and we try to lower the chances that a similar bug makes it in another time. That's done by making `QueryShardContext` return the fully qualified `Index` (which also holds the uuid) rather than only the fully qualified index name.
1 parent 6fe6247 commit c474c74

File tree

7 files changed

+107
-57
lines changed

7 files changed

+107
-57
lines changed

modules/percolator/src/main/java/org/elasticsearch/percolator/PercolateQueryBuilder.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -756,13 +756,12 @@ public BitSetProducer bitsetFilter(Query query) {
756756
@Override
757757
@SuppressWarnings("unchecked")
758758
public <IFD extends IndexFieldData<?>> IFD getForField(MappedFieldType fieldType) {
759-
IndexFieldData.Builder builder = fieldType.fielddataBuilder(shardContext.getFullyQualifiedIndexName());
759+
IndexFieldData.Builder builder = fieldType.fielddataBuilder(shardContext.getFullyQualifiedIndex().getName());
760760
IndexFieldDataCache cache = new IndexFieldDataCache.None();
761761
CircuitBreakerService circuitBreaker = new NoneCircuitBreakerService();
762762
return (IFD) builder.build(shardContext.getIndexSettings(), fieldType, cache, circuitBreaker,
763763
shardContext.getMapperService());
764764
}
765765
};
766766
}
767-
768767
}

server/src/main/java/org/elasticsearch/index/mapper/IndexFieldMapper.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public Query existsQuery(QueryShardContext context) {
126126
*/
127127
@Override
128128
public Query termQuery(Object value, @Nullable QueryShardContext context) {
129-
if (isSameIndex(value, context.getFullyQualifiedIndexName())) {
129+
if (isSameIndex(value, context.getFullyQualifiedIndex().getName())) {
130130
return Queries.newMatchAllQuery();
131131
} else {
132132
return Queries.newMatchNoDocsQuery("Index didn't match. Index queried: " + context.index().getName() + " vs. " + value);
@@ -139,14 +139,14 @@ public Query termsQuery(List values, QueryShardContext context) {
139139
return super.termsQuery(values, context);
140140
}
141141
for (Object value : values) {
142-
if (isSameIndex(value, context.getFullyQualifiedIndexName())) {
142+
if (isSameIndex(value, context.getFullyQualifiedIndex().getName())) {
143143
// No need to OR these clauses - we can only logically be
144144
// running in the context of just one of these index names.
145145
return Queries.newMatchAllQuery();
146146
}
147147
}
148148
// None of the listed index names are this one
149-
return Queries.newMatchNoDocsQuery("Index didn't match. Index queried: " + context.getFullyQualifiedIndexName()
149+
return Queries.newMatchNoDocsQuery("Index didn't match. Index queried: " + context.getFullyQualifiedIndex().getName()
150150
+ " vs. " + values);
151151
}
152152

@@ -189,5 +189,4 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
189189
protected void doMerge(Mapper mergeWith) {
190190
// nothing to do
191191
}
192-
193192
}

server/src/main/java/org/elasticsearch/index/query/QueryShardContext.java

+8-7
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public class QueryShardContext extends QueryRewriteContext {
8383
private String[] types = Strings.EMPTY_ARRAY;
8484
private boolean cachable = true;
8585
private final SetOnce<Boolean> frozen = new SetOnce<>();
86-
private final String fullyQualifiedIndexName;
86+
private final Index fullyQualifiedIndex;
8787

8888
public void setTypes(String... types) {
8989
this.types = types;
@@ -116,7 +116,8 @@ public QueryShardContext(int shardId, IndexSettings indexSettings, BitsetFilterC
116116
this.indexSettings = indexSettings;
117117
this.reader = reader;
118118
this.clusterAlias = clusterAlias;
119-
this.fullyQualifiedIndexName = RemoteClusterAware.buildRemoteIndexName(clusterAlias, indexSettings.getIndex().getName());
119+
this.fullyQualifiedIndex = new Index(RemoteClusterAware.buildRemoteIndexName(clusterAlias, indexSettings.getIndex().getName()),
120+
indexSettings.getIndex().getUUID());
120121
}
121122

122123
public QueryShardContext(QueryShardContext source) {
@@ -163,7 +164,7 @@ public BitSetProducer bitsetFilter(Query filter) {
163164
}
164165

165166
public <IFD extends IndexFieldData<?>> IFD getForField(MappedFieldType fieldType) {
166-
return (IFD) indexFieldDataService.apply(fieldType, fullyQualifiedIndexName);
167+
return (IFD) indexFieldDataService.apply(fieldType, fullyQualifiedIndex.getName());
167168
}
168169

169170
public void addNamedQuery(String name, Query query) {
@@ -275,7 +276,7 @@ public Collection<String> queryTypes() {
275276
public SearchLookup lookup() {
276277
if (lookup == null) {
277278
lookup = new SearchLookup(getMapperService(),
278-
mappedFieldType -> indexFieldDataService.apply(mappedFieldType, fullyQualifiedIndexName), types);
279+
mappedFieldType -> indexFieldDataService.apply(mappedFieldType, fullyQualifiedIndex.getName()), types);
279280
}
280281
return lookup;
281282
}
@@ -426,9 +427,9 @@ public IndexReader getIndexReader() {
426427
}
427428

428429
/**
429-
* Returns the fully qualified index name including a remote cluster alias if applicable
430+
* Returns the fully qualified index including a remote cluster alias if applicable, and the index uuid
430431
*/
431-
public String getFullyQualifiedIndexName() {
432-
return fullyQualifiedIndexName;
432+
public Index getFullyQualifiedIndex() {
433+
return fullyQualifiedIndex;
433434
}
434435
}

server/src/main/java/org/elasticsearch/index/query/QueryShardException.java

+3-4
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,15 @@ public QueryShardException(QueryShardContext context, String msg, Object... args
3737
}
3838

3939
public QueryShardException(QueryShardContext context, String msg, Throwable cause, Object... args) {
40-
super(msg, cause, args);
41-
setIndex(context.getFullyQualifiedIndexName());
40+
this(context.getFullyQualifiedIndex(), msg, cause, args);
4241
}
4342

4443
/**
4544
* This constructor is provided for use in unit tests where a
4645
* {@link QueryShardContext} may not be available
4746
*/
48-
public QueryShardException(Index index, String msg, Throwable cause) {
49-
super(msg, cause);
47+
public QueryShardException(Index index, String msg, Throwable cause, Object... args) {
48+
super(msg, cause, args);
5049
setIndex(index);
5150
}
5251

server/src/test/java/org/elasticsearch/index/query/QueryShardContextTests.java

+38-38
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222
import org.apache.lucene.search.Query;
2323
import org.elasticsearch.Version;
2424
import org.elasticsearch.cluster.metadata.IndexMetaData;
25+
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
2526
import org.elasticsearch.common.lucene.search.Queries;
2627
import org.elasticsearch.common.settings.Settings;
28+
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
2729
import org.elasticsearch.index.IndexSettings;
2830
import org.elasticsearch.index.fielddata.IndexFieldData;
2931
import org.elasticsearch.index.fielddata.plain.AbstractAtomicOrdinalsFieldData;
@@ -37,6 +39,7 @@
3739
import org.hamcrest.Matchers;
3840

3941
import java.io.IOException;
42+
import java.util.Collections;
4043

4144
import static org.hamcrest.Matchers.equalTo;
4245
import static org.hamcrest.Matchers.instanceOf;
@@ -49,24 +52,7 @@
4952
public class QueryShardContextTests extends ESTestCase {
5053

5154
public void testFailIfFieldMappingNotFound() {
52-
IndexMetaData.Builder indexMetadataBuilder = new IndexMetaData.Builder("index");
53-
indexMetadataBuilder.settings(Settings.builder().put("index.version.created", Version.CURRENT)
54-
.put("index.number_of_shards", 1)
55-
.put("index.number_of_replicas", 1)
56-
);
57-
IndexMetaData indexMetaData = indexMetadataBuilder.build();
58-
IndexSettings indexSettings = new IndexSettings(indexMetaData, Settings.EMPTY);
59-
MapperService mapperService = mock(MapperService.class);
60-
when(mapperService.getIndexSettings()).thenReturn(indexSettings);
61-
when(mapperService.index()).thenReturn(indexMetaData.getIndex());
62-
final long nowInMillis = randomNonNegativeLong();
63-
64-
QueryShardContext context = new QueryShardContext(
65-
0, indexSettings, null, (mappedFieldType, idxName) ->
66-
mappedFieldType.fielddataBuilder(idxName).build(indexSettings, mappedFieldType, null, null, null)
67-
, mapperService, null, null, xContentRegistry(), writableRegistry(), null, null,
68-
() -> nowInMillis, null);
69-
55+
QueryShardContext context = createQueryShardContext(IndexMetaData.INDEX_UUID_NA_VALUE, null);
7056
context.setAllowUnmappedFields(false);
7157
MappedFieldType fieldType = new TextFieldMapper.TextFieldType();
7258
MappedFieldType result = context.failIfFieldMappingNotFound("name", fieldType);
@@ -91,30 +77,16 @@ public void testFailIfFieldMappingNotFound() {
9177
}
9278

9379
public void testClusterAlias() throws IOException {
94-
IndexMetaData.Builder indexMetadataBuilder = new IndexMetaData.Builder("index");
95-
indexMetadataBuilder.settings(Settings.builder().put("index.version.created", Version.CURRENT)
96-
.put("index.number_of_shards", 1)
97-
.put("index.number_of_replicas", 1)
98-
);
99-
IndexMetaData indexMetaData = indexMetadataBuilder.build();
100-
IndexSettings indexSettings = new IndexSettings(indexMetaData, Settings.EMPTY);
101-
MapperService mapperService = mock(MapperService.class);
102-
when(mapperService.getIndexSettings()).thenReturn(indexSettings);
103-
when(mapperService.index()).thenReturn(indexMetaData.getIndex());
104-
final long nowInMillis = randomNonNegativeLong();
80+
final String clusterAlias = randomBoolean() ? null : "remote_cluster";
81+
QueryShardContext context = createQueryShardContext(IndexMetaData.INDEX_UUID_NA_VALUE, clusterAlias);
10582

106-
Mapper.BuilderContext ctx = new Mapper.BuilderContext(indexSettings.getSettings(), new ContentPath());
83+
84+
Mapper.BuilderContext ctx = new Mapper.BuilderContext(context.getIndexSettings().getSettings(), new ContentPath());
10785
IndexFieldMapper mapper = new IndexFieldMapper.Builder(null).build(ctx);
108-
final String clusterAlias = randomBoolean() ? null : "remote_cluster";
109-
QueryShardContext context = new QueryShardContext(
110-
0, indexSettings, null, (mappedFieldType, indexname) ->
111-
mappedFieldType.fielddataBuilder(indexname).build(indexSettings, mappedFieldType, null, null, mapperService)
112-
, mapperService, null, null, xContentRegistry(), writableRegistry(), null, null,
113-
() -> nowInMillis, clusterAlias);
11486

11587
IndexFieldData<?> forField = context.getForField(mapper.fieldType());
116-
String expected = clusterAlias == null ? indexMetaData.getIndex().getName()
117-
: clusterAlias + ":" + indexMetaData.getIndex().getName();
88+
String expected = clusterAlias == null ? context.getIndexSettings().getIndexMetaData().getIndex().getName()
89+
: clusterAlias + ":" + context.getIndexSettings().getIndex().getName();
11890
assertEquals(expected, ((AbstractAtomicOrdinalsFieldData)forField.load(null)).getOrdinalsValues().lookupOrd(0).utf8ToString());
11991
Query query = mapper.fieldType().termQuery("index", context);
12092
if (clusterAlias == null) {
@@ -133,4 +105,32 @@ public void testClusterAlias() throws IOException {
133105
assertThat(query, Matchers.instanceOf(MatchNoDocsQuery.class));
134106
}
135107

108+
public void testGetFullyQualifiedIndex() {
109+
String clusterAlias = randomAlphaOfLengthBetween(5, 10);
110+
String indexUuid = randomAlphaOfLengthBetween(3, 10);
111+
QueryShardContext shardContext = createQueryShardContext(indexUuid, clusterAlias);
112+
assertThat(shardContext.getFullyQualifiedIndex().getName(), equalTo(clusterAlias + ":index"));
113+
assertThat(shardContext.getFullyQualifiedIndex().getUUID(), equalTo(indexUuid));
114+
}
115+
116+
public static QueryShardContext createQueryShardContext(String indexUuid, String clusterAlias) {
117+
IndexMetaData.Builder indexMetadataBuilder = new IndexMetaData.Builder("index");
118+
indexMetadataBuilder.settings(Settings.builder().put("index.version.created", Version.CURRENT)
119+
.put("index.number_of_shards", 1)
120+
.put("index.number_of_replicas", 1)
121+
.put(IndexMetaData.SETTING_INDEX_UUID, indexUuid)
122+
);
123+
IndexMetaData indexMetaData = indexMetadataBuilder.build();
124+
IndexSettings indexSettings = new IndexSettings(indexMetaData, Settings.EMPTY);
125+
MapperService mapperService = mock(MapperService.class);
126+
when(mapperService.getIndexSettings()).thenReturn(indexSettings);
127+
when(mapperService.index()).thenReturn(indexMetaData.getIndex());
128+
final long nowInMillis = randomNonNegativeLong();
129+
130+
return new QueryShardContext(
131+
0, indexSettings, null, (mappedFieldType, idxName) ->
132+
mappedFieldType.fielddataBuilder(idxName).build(indexSettings, mappedFieldType, null, null, null)
133+
, mapperService, null, null, NamedXContentRegistry.EMPTY, new NamedWriteableRegistry(Collections.emptyList()), null, null,
134+
() -> nowInMillis, clusterAlias);
135+
}
136136
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.index.query;
21+
22+
import org.elasticsearch.index.Index;
23+
import org.elasticsearch.test.ESTestCase;
24+
25+
import static org.hamcrest.CoreMatchers.equalTo;
26+
27+
public class QueryShardExceptionTests extends ESTestCase {
28+
29+
public void testCreateFromQueryShardContext() {
30+
String indexUuid = randomAlphaOfLengthBetween(5, 10);
31+
String clusterAlias = randomAlphaOfLengthBetween(5, 10);
32+
QueryShardContext queryShardContext = QueryShardContextTests.createQueryShardContext(indexUuid, clusterAlias);
33+
{
34+
QueryShardException queryShardException = new QueryShardException(queryShardContext, "error");
35+
assertThat(queryShardException.getIndex().getName(), equalTo(clusterAlias + ":index"));
36+
assertThat(queryShardException.getIndex().getUUID(), equalTo(indexUuid));
37+
}
38+
{
39+
QueryShardException queryShardException = new QueryShardException(queryShardContext, "error", new IllegalArgumentException());
40+
assertThat(queryShardException.getIndex().getName(), equalTo(clusterAlias + ":index"));
41+
assertThat(queryShardException.getIndex().getUUID(), equalTo(indexUuid));
42+
}
43+
}
44+
45+
public void testCreateFromIndex() {
46+
String indexUuid = randomAlphaOfLengthBetween(5, 10);
47+
String indexName = randomAlphaOfLengthBetween(5, 10);
48+
Index index = new Index(indexName, indexUuid);
49+
QueryShardException queryShardException = new QueryShardException(index, "error", new IllegalArgumentException());
50+
assertThat(queryShardException.getIndex().getName(), equalTo(indexName));
51+
assertThat(queryShardException.getIndex().getUUID(), equalTo(indexUuid));
52+
}
53+
}

server/src/test/java/org/elasticsearch/index/query/WildcardQueryBuilderTests.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import java.util.HashMap;
3333
import java.util.Map;
3434

35-
import static org.elasticsearch.test.AbstractBuilderTestCase.STRING_ALIAS_FIELD_NAME;
3635
import static org.hamcrest.Matchers.equalTo;
3736
import static org.hamcrest.Matchers.instanceOf;
3837

@@ -143,7 +142,7 @@ public void testWithMetaDataField() throws IOException {
143142

144143
public void testIndexWildcard() throws IOException {
145144
QueryShardContext context = createShardContext();
146-
String index = context.getFullyQualifiedIndexName();
145+
String index = context.getFullyQualifiedIndex().getName();
147146

148147
Query query = new WildcardQueryBuilder("_index", index).doToQuery(context);
149148
assertThat(query instanceof MatchAllDocsQuery, equalTo(true));

0 commit comments

Comments
 (0)