Skip to content

Commit bdb6c35

Browse files
authored
Clarify when shard iterators get sorted (elastic#52633)
Currently we have two ways to create a GroupShardsIterator: one that will resort the iterators based on their natural ordering, and another one that will leave them in their original order. This is currently done through two constructors, one that accepts a single argument which does the sorting, and another which accepts a second boolean argument to control whether sorting should happen or not. This second constructor is only called externally to disable the sorting. By introducing a specific method to create a sorted shard iterator we clarify and make it easier to track when we do sort and when we do not as the iterators are externally sorted.
1 parent 35356dd commit bdb6c35

File tree

7 files changed

+66
-34
lines changed

7 files changed

+66
-34
lines changed

server/src/main/java/org/elasticsearch/action/search/AbstractSearchAsyncAction.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ abstract class AbstractSearchAsyncAction<Result extends SearchPhaseResult> exten
116116
iterators.add(iterator);
117117
}
118118
}
119-
this.toSkipShardsIts = new GroupShardsIterator<>(toSkipIterators, false);
120-
this.shardsIts = new GroupShardsIterator<>(iterators, false);
119+
this.toSkipShardsIts = new GroupShardsIterator<>(toSkipIterators);
120+
this.shardsIts = new GroupShardsIterator<>(iterators);
121121
// we need to add 1 for non active partition, since we count it in the total. This means for each shard in the iterator we sum up
122122
// it's number of active shards but use 1 as the default if no replica of a shard is active at this point.
123123
// on a per shards level we use shardIt.remaining() to increment the totalOps pointer but add 1 for the current shard result

server/src/main/java/org/elasticsearch/action/search/CanMatchPreFilterSearchPhase.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ private GroupShardsIterator<SearchShardIterator> getIterator(CanMatchSearchPhase
113113
return shardsIts;
114114
}
115115
FieldSortBuilder fieldSort = FieldSortBuilder.getPrimaryFieldSortOrNull(source);
116-
return new GroupShardsIterator<>(sortShards(shardsIts, results.minAndMaxes, fieldSort.order()), false);
116+
return new GroupShardsIterator<>(sortShards(shardsIts, results.minAndMaxes, fieldSort.order()));
117117
}
118118

119119
private static List<SearchShardIterator> sortShards(GroupShardsIterator<SearchShardIterator> shardsIts,
@@ -122,7 +122,7 @@ private static List<SearchShardIterator> sortShards(GroupShardsIterator<SearchSh
122122
return IntStream.range(0, shardsIts.size())
123123
.boxed()
124124
.sorted(shardComparator(shardsIts, minAndMaxes, order))
125-
.map(ord -> shardsIts.get(ord))
125+
.map(shardsIts::get)
126126
.collect(Collectors.toList());
127127
}
128128

server/src/main/java/org/elasticsearch/action/search/TransportSearchAction.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -553,10 +553,10 @@ static GroupShardsIterator<SearchShardIterator> mergeShardsIterators(GroupShards
553553
for (ShardIterator shardIterator : localShardsIterator) {
554554
shards.add(new SearchShardIterator(localClusterAlias, shardIterator.shardId(), shardIterator.getShardRoutings(), localIndices));
555555
}
556-
return new GroupShardsIterator<>(shards);
556+
return GroupShardsIterator.sortAndCreate(shards);
557557
}
558558

559-
private AbstractSearchAsyncAction searchAsyncAction(SearchTask task, SearchRequest searchRequest,
559+
private AbstractSearchAsyncAction<? extends SearchPhaseResult> searchAsyncAction(SearchTask task, SearchRequest searchRequest,
560560
GroupShardsIterator<SearchShardIterator> shardIterators,
561561
SearchTimeProvider timeProvider,
562562
BiFunction<String, String, Transport.Connection> connectionLookup,
@@ -572,8 +572,19 @@ private AbstractSearchAsyncAction searchAsyncAction(SearchTask task, SearchReque
572572
return new CanMatchPreFilterSearchPhase(logger, searchTransportService, connectionLookup,
573573
aliasFilter, concreteIndexBoosts, indexRoutings, executor, searchRequest, listener, shardIterators,
574574
timeProvider, clusterStateVersion, task, (iter) -> {
575-
AbstractSearchAsyncAction action = searchAsyncAction(task, searchRequest, iter, timeProvider, connectionLookup,
576-
clusterStateVersion, aliasFilter, concreteIndexBoosts, indexRoutings, listener, false, clusters);
575+
AbstractSearchAsyncAction<? extends SearchPhaseResult> action = searchAsyncAction(
576+
task,
577+
searchRequest,
578+
iter,
579+
timeProvider,
580+
connectionLookup,
581+
clusterStateVersion,
582+
aliasFilter,
583+
concreteIndexBoosts,
584+
indexRoutings,
585+
listener,
586+
false,
587+
clusters);
577588
return new SearchPhase(action.getName()) {
578589
@Override
579590
public void run() {

server/src/main/java/org/elasticsearch/cluster/routing/GroupShardsIterator.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,19 @@ public final class GroupShardsIterator<ShardIt extends ShardIterator> implements
3535
private final List<ShardIt> iterators;
3636

3737
/**
38-
* Constructs a enw GroupShardsIterator from the given list.
38+
* Constructs a new sorted GroupShardsIterator from the given list. Items are sorted based on their natural ordering.
39+
* @see PlainShardIterator#compareTo(ShardIterator)
40+
* @see org.elasticsearch.action.search.SearchShardIterator#compareTo(ShardIterator)
3941
*/
40-
public GroupShardsIterator(List<ShardIt> iterators) {
41-
this(iterators, true);
42+
public static <ShardIt extends ShardIterator> GroupShardsIterator<ShardIt> sortAndCreate(List<ShardIt> iterators) {
43+
CollectionUtil.timSort(iterators);
44+
return new GroupShardsIterator<>(iterators);
4245
}
4346

4447
/**
4548
* Constructs a new GroupShardsIterator from the given list.
4649
*/
47-
public GroupShardsIterator(List<ShardIt> iterators, boolean useSort) {
48-
if (useSort) {
49-
CollectionUtil.timSort(iterators);
50-
}
50+
public GroupShardsIterator(List<ShardIt> iterators) {
5151
this.iterators = iterators;
5252
}
5353

server/src/main/java/org/elasticsearch/cluster/routing/OperationRouting.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public GroupShardsIterator<ShardIterator> searchShards(ClusterState clusterState
9595
set.add(iterator);
9696
}
9797
}
98-
return new GroupShardsIterator<>(new ArrayList<>(set));
98+
return GroupShardsIterator.sortAndCreate(new ArrayList<>(set));
9999
}
100100

101101
private static final Map<String, Set<String>> EMPTY_ROUTING = Collections.emptyMap();

server/src/main/java/org/elasticsearch/cluster/routing/RoutingTable.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ private GroupShardsIterator<ShardIterator> allSatisfyingPredicateShardsGrouped(S
260260
}
261261
}
262262
}
263-
return new GroupShardsIterator<>(set);
263+
return GroupShardsIterator.sortAndCreate(set);
264264
}
265265

266266
public ShardsIterator allShards(String[] indices) {
@@ -321,7 +321,7 @@ public GroupShardsIterator<ShardIterator> activePrimaryShardsGrouped(String[] in
321321
}
322322
}
323323
}
324-
return new GroupShardsIterator<>(set);
324+
return GroupShardsIterator.sortAndCreate(set);
325325
}
326326

327327
@Override

server/src/test/java/org/elasticsearch/cluster/routing/GroupShardsIteratorTests.java

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public void testSize() {
6969
ShardId shardId = new ShardId(index, 1);
7070
list.add(new PlainShardIterator(shardId, randomShardRoutings(shardId, 0)));
7171
}
72-
GroupShardsIterator iter = new GroupShardsIterator<>(list);
72+
GroupShardsIterator<ShardIterator> iter = new GroupShardsIterator<>(list);
7373
assertEquals(7, iter.totalSizeWith1ForEmpty());
7474
assertEquals(5, iter.size());
7575
assertEquals(6, iter.totalSize());
@@ -106,13 +106,24 @@ public void testIterate() {
106106
}
107107

108108
Collections.shuffle(list, random());
109-
List<ShardIterator> actualIterators = new ArrayList<>();
110-
GroupShardsIterator<ShardIterator> iter = new GroupShardsIterator<>(list);
111-
for (ShardIterator shardsIterator : iter) {
112-
actualIterators.add(shardsIterator);
109+
{
110+
GroupShardsIterator<ShardIterator> unsorted = new GroupShardsIterator<>(list);
111+
GroupShardsIterator<ShardIterator> iter = new GroupShardsIterator<>(list);
112+
List<ShardIterator> actualIterators = new ArrayList<>();
113+
for (ShardIterator shardsIterator : iter) {
114+
actualIterators.add(shardsIterator);
115+
}
116+
assertEquals(actualIterators, list);
117+
}
118+
{
119+
GroupShardsIterator<ShardIterator> iter = GroupShardsIterator.sortAndCreate(list);
120+
List<ShardIterator> actualIterators = new ArrayList<>();
121+
for (ShardIterator shardsIterator : iter) {
122+
actualIterators.add(shardsIterator);
123+
}
124+
CollectionUtil.timSort(actualIterators);
125+
assertEquals(actualIterators, list);
113126
}
114-
CollectionUtil.timSort(actualIterators);
115-
assertEquals(actualIterators, list);
116127
}
117128

118129
public void testOrderingWithSearchShardIterators() {
@@ -123,31 +134,41 @@ public void testOrderingWithSearchShardIterators() {
123134
String[] clusters = generateRandomStringArray(5, 10, false, false);
124135
Arrays.sort(clusters);
125136

126-
List<SearchShardIterator> expected = new ArrayList<>();
137+
List<SearchShardIterator> sorted = new ArrayList<>();
127138
int numShards = randomIntBetween(1, 10);
128139
for (int i = 0; i < numShards; i++) {
129140
for (String index : indices) {
130141
for (String uuid : uuids) {
131142
ShardId shardId = new ShardId(index, uuid, i);
132143
SearchShardIterator shardIterator = new SearchShardIterator(null, shardId,
133144
GroupShardsIteratorTests.randomShardRoutings(shardId), OriginalIndicesTests.randomOriginalIndices());
134-
expected.add(shardIterator);
145+
sorted.add(shardIterator);
135146
for (String cluster : clusters) {
136147
SearchShardIterator remoteIterator = new SearchShardIterator(cluster, shardId,
137148
GroupShardsIteratorTests.randomShardRoutings(shardId), OriginalIndicesTests.randomOriginalIndices());
138-
expected.add(remoteIterator);
149+
sorted.add(remoteIterator);
139150
}
140151
}
141152
}
142153
}
143154

144-
List<SearchShardIterator> shuffled = new ArrayList<>(expected);
155+
List<SearchShardIterator> shuffled = new ArrayList<>(sorted);
145156
Collections.shuffle(shuffled, random());
146-
List<ShardIterator> actualIterators = new ArrayList<>();
147-
GroupShardsIterator<SearchShardIterator> iter = new GroupShardsIterator<>(shuffled);
148-
for (SearchShardIterator searchShardIterator : iter) {
149-
actualIterators.add(searchShardIterator);
157+
{
158+
List<ShardIterator> actualIterators = new ArrayList<>();
159+
GroupShardsIterator<SearchShardIterator> iter = new GroupShardsIterator<>(shuffled);
160+
for (SearchShardIterator searchShardIterator : iter) {
161+
actualIterators.add(searchShardIterator);
162+
}
163+
assertEquals(shuffled, actualIterators);
164+
}
165+
{
166+
List<ShardIterator> actualIterators = new ArrayList<>();
167+
GroupShardsIterator<SearchShardIterator> iter = GroupShardsIterator.sortAndCreate(shuffled);
168+
for (SearchShardIterator searchShardIterator : iter) {
169+
actualIterators.add(searchShardIterator);
170+
}
171+
assertEquals(sorted, actualIterators);
150172
}
151-
assertEquals(expected, actualIterators);
152173
}
153174
}

0 commit comments

Comments
 (0)