@@ -348,8 +348,8 @@ private DfsSearchResult executeDfsPhase(ShardSearchRequest request,
348
348
SearchShardTask task ,
349
349
boolean keepStatesInContext ) throws IOException {
350
350
ReaderContext readerContext = createOrGetReaderContext (request , keepStatesInContext );
351
- try (Releasable ignored = readerContext . markAsUsed ( );
352
- SearchContext context = createContext (readerContext , request , task , true )) {
351
+ try (Releasable ignored = updateKeepAliveAndMarkAsUsed ( readerContext , getKeepAlive ( request ) );
352
+ SearchContext context = createContext (readerContext , request , task , true )) {
353
353
dfsPhase .execute (context );
354
354
return context .dfsResult ();
355
355
} catch (Exception e ) {
@@ -380,49 +380,24 @@ public void executeQueryPhase(ShardSearchRequest request, boolean keepStatesInCo
380
380
rewriteAndFetchShardRequest (shard , request , new ActionListener <ShardSearchRequest >() {
381
381
@ Override
382
382
public void onResponse (ShardSearchRequest orig ) {
383
- final ReaderContext readerContext = createOrGetReaderContext (orig , keepStatesInContext );
384
- final Releasable markAsUsed = readerContext .markAsUsed ();
383
+ // check if we can shortcut the query phase entirely.
385
384
if (orig .canReturnNullResponseIfMatchNoDocs ()) {
386
385
assert orig .scroll () == null ;
387
- // we clone the shard request and perform a quick rewrite using a lightweight
388
- // searcher since we are outside of the search thread pool.
389
- // If the request rewrites to "match none" we can shortcut the query phase
390
- // entirely. Otherwise we fork the execution in the search thread pool.
391
- ShardSearchRequest canMatchRequest = new ShardSearchRequest (orig );
392
- try (Engine .Searcher searcher = readerContext .acquireSearcher (Engine .CAN_MATCH_SEARCH_SOURCE )) {
393
- QueryShardContext context = readerContext .indexService ().newQueryShardContext (canMatchRequest .shardId ().id (),
394
- searcher , canMatchRequest ::nowInMillis , canMatchRequest .getClusterAlias ());
395
- Rewriteable .rewrite (canMatchRequest .getRewriteable (), context , true );
386
+ final CanMatchResponse canMatchResp ;
387
+ try {
388
+ ShardSearchRequest clone = new ShardSearchRequest (orig );
389
+ canMatchResp = canMatch (clone , false );
396
390
} catch (Exception exc ) {
397
- try (markAsUsed ) {
398
- listener .onFailure (exc );
399
- } finally {
400
- processFailure (readerContext , exc );
401
- }
391
+ listener .onFailure (exc );
402
392
return ;
403
393
}
404
- if (canRewriteToMatchNone (canMatchRequest .source ())
405
- && canMatchRequest .source ().query () instanceof MatchNoneQueryBuilder ) {
406
- try (markAsUsed ) {
407
- if (orig .readerId () == null ) {
408
- try {
409
- listener .onResponse (QuerySearchResult .nullInstance ());
410
- } finally {
411
- // close and remove the ephemeral reader context
412
- removeReaderContext (readerContext .id ().getId ());
413
- Releasables .close (readerContext );
414
- }
415
- } else {
416
- listener .onResponse (QuerySearchResult .nullInstance ());
417
- }
418
- }
394
+ if (canMatchResp .canMatch == false ) {
395
+ listener .onResponse (QuerySearchResult .nullInstance ());
419
396
return ;
420
397
}
421
398
}
422
-
423
399
// fork the execution in the search thread pool
424
- runAsync (getExecutor (shard ), () -> executeQueryPhase (orig , task , readerContext ),
425
- wrapFailureListener (listener , readerContext , markAsUsed ));
400
+ runAsync (getExecutor (shard ), () -> executeQueryPhase (orig , task , keepStatesInContext ), listener );
426
401
}
427
402
428
403
@ Override
@@ -446,8 +421,10 @@ private <T> void runAsync(Executor executor, CheckedSupplier<T, Exception> execu
446
421
447
422
private SearchPhaseResult executeQueryPhase (ShardSearchRequest request ,
448
423
SearchShardTask task ,
449
- ReaderContext readerContext ) throws Exception {
450
- try (SearchContext context = createContext (readerContext , request , task , true )) {
424
+ boolean keepStatesInContext ) throws Exception {
425
+ final ReaderContext readerContext = createOrGetReaderContext (request , keepStatesInContext );
426
+ try (Releasable ignored = updateKeepAliveAndMarkAsUsed (readerContext , getKeepAlive (request ));
427
+ SearchContext context = createContext (readerContext , request , task , true )) {
451
428
final long afterQueryTime ;
452
429
try (SearchOperationListenerExecutor executor = new SearchOperationListenerExecutor (context )) {
453
430
loadOrExecuteQueryPhase (request , context );
@@ -494,16 +471,11 @@ public void executeQueryPhase(InternalScrollSearchRequest request,
494
471
SearchShardTask task ,
495
472
ActionListener <ScrollQuerySearchResult > listener ) {
496
473
final LegacyReaderContext readerContext = (LegacyReaderContext ) findReaderContext (request .contextId (), request );
497
- final Releasable markAsUsed = readerContext . markAsUsed ( );
474
+ final Releasable markAsUsed = updateKeepAliveAndMarkAsUsed ( readerContext , getScrollKeepAlive ( request . scroll ()) );
498
475
runAsync (getExecutor (readerContext .indexShard ()), () -> {
499
476
final ShardSearchRequest shardSearchRequest = readerContext .getShardSearchRequest (null );
500
477
try (SearchContext searchContext = createContext (readerContext , shardSearchRequest , task , false );
501
478
SearchOperationListenerExecutor executor = new SearchOperationListenerExecutor (searchContext )) {
502
- if (request .scroll () != null && request .scroll ().keepAlive () != null ) {
503
- final long keepAlive = request .scroll ().keepAlive ().millis ();
504
- checkKeepAliveLimit (keepAlive );
505
- readerContext .keepAlive (keepAlive );
506
- }
507
479
searchContext .searcher ().setAggregatedDfs (readerContext .getAggregatedDfs (null ));
508
480
processScroll (request , readerContext , searchContext );
509
481
queryPhase .execute (searchContext );
@@ -519,10 +491,10 @@ public void executeQueryPhase(InternalScrollSearchRequest request,
519
491
}
520
492
521
493
public void executeQueryPhase (QuerySearchRequest request , SearchShardTask task , ActionListener <QuerySearchResult > listener ) {
522
- final ReaderContext readerContext = findReaderContext (request .contextId (), request );
523
- final Releasable markAsUsed = readerContext .markAsUsed ();
494
+ final ReaderContext readerContext = findReaderContext (request .contextId (), request .shardSearchRequest ());
495
+ final ShardSearchRequest shardSearchRequest = readerContext .getShardSearchRequest (request .shardSearchRequest ());
496
+ final Releasable markAsUsed = updateKeepAliveAndMarkAsUsed (readerContext , getKeepAlive (shardSearchRequest ));
524
497
runAsync (getExecutor (readerContext .indexShard ()), () -> {
525
- final ShardSearchRequest shardSearchRequest = readerContext .getShardSearchRequest (request .shardSearchRequest ());
526
498
readerContext .setAggregatedDfs (request .dfs ());
527
499
try (SearchContext searchContext = createContext (readerContext , shardSearchRequest , task , true );
528
500
SearchOperationListenerExecutor executor = new SearchOperationListenerExecutor (searchContext )) {
@@ -564,15 +536,11 @@ private Executor getExecutor(IndexShard indexShard) {
564
536
public void executeFetchPhase (InternalScrollSearchRequest request , SearchShardTask task ,
565
537
ActionListener <ScrollQueryFetchSearchResult > listener ) {
566
538
final LegacyReaderContext readerContext = (LegacyReaderContext ) findReaderContext (request .contextId (), request );
567
- final Releasable markAsUsed = readerContext . markAsUsed ( );
539
+ final Releasable markAsUsed = updateKeepAliveAndMarkAsUsed ( readerContext , getScrollKeepAlive ( request . scroll ()) );
568
540
runAsync (getExecutor (readerContext .indexShard ()), () -> {
569
541
final ShardSearchRequest shardSearchRequest = readerContext .getShardSearchRequest (null );
570
542
try (SearchContext searchContext = createContext (readerContext , shardSearchRequest , task , false );
571
543
SearchOperationListenerExecutor executor = new SearchOperationListenerExecutor (searchContext )) {
572
- if (request .scroll () != null && request .scroll ().keepAlive () != null ) {
573
- checkKeepAliveLimit (request .scroll ().keepAlive ().millis ());
574
- readerContext .keepAlive (request .scroll ().keepAlive ().millis ());
575
- }
576
544
searchContext .assignRescoreDocIds (readerContext .getRescoreDocIds (null ));
577
545
searchContext .searcher ().setAggregatedDfs (readerContext .getAggregatedDfs (null ));
578
546
processScroll (request , readerContext , searchContext );
@@ -591,9 +559,9 @@ public void executeFetchPhase(InternalScrollSearchRequest request, SearchShardTa
591
559
592
560
public void executeFetchPhase (ShardFetchRequest request , SearchShardTask task , ActionListener <FetchSearchResult > listener ) {
593
561
final ReaderContext readerContext = findReaderContext (request .contextId (), request );
594
- final Releasable markAsUsed = readerContext .markAsUsed ();
562
+ final ShardSearchRequest shardSearchRequest = readerContext .getShardSearchRequest (request .getShardSearchRequest ());
563
+ final Releasable markAsUsed = updateKeepAliveAndMarkAsUsed (readerContext , getKeepAlive (shardSearchRequest ));
595
564
runAsync (getExecutor (readerContext .indexShard ()), () -> {
596
- final ShardSearchRequest shardSearchRequest = readerContext .getShardSearchRequest (request .getShardSearchRequest ());
597
565
try (SearchContext searchContext = createContext (readerContext , shardSearchRequest , task , false )) {
598
566
if (request .lastEmittedDoc () != null ) {
599
567
searchContext .scrollContext ().lastEmittedDoc = request .lastEmittedDoc ();
@@ -643,13 +611,18 @@ private ReaderContext findReaderContext(ShardSearchContextId id, TransportReques
643
611
return reader ;
644
612
}
645
613
614
+ private Releasable updateKeepAliveAndMarkAsUsed (ReaderContext reader , long keepAlive ) {
615
+ if (keepAlive > 0L ) {
616
+ checkKeepAliveLimit (keepAlive );
617
+ reader .keepAlive (keepAlive );
618
+ }
619
+ return reader .markAsUsed ();
620
+ }
621
+
646
622
final ReaderContext createOrGetReaderContext (ShardSearchRequest request , boolean keepStatesInContext ) {
647
623
if (request .readerId () != null ) {
648
624
assert keepStatesInContext == false ;
649
625
final ReaderContext readerContext = findReaderContext (request .readerId (), request );
650
- final long keepAlive = request .keepAlive ().millis ();
651
- checkKeepAliveLimit (keepAlive );
652
- readerContext .keepAlive (keepAlive );
653
626
return readerContext ;
654
627
}
655
628
IndexService indexService = indicesService .indexServiceSafe (request .shardId ().getIndex ());
@@ -835,11 +808,20 @@ public void freeAllScrollContexts() {
835
808
}
836
809
837
810
private long getKeepAlive (ShardSearchRequest request ) {
838
- if (request .scroll () != null && request .scroll ().keepAlive () != null ) {
839
- return request .scroll ().keepAlive ().millis ();
811
+ if (request .scroll () != null ) {
812
+ return getScrollKeepAlive (request .scroll ());
813
+ } else if (request .keepAlive () != null ) {
814
+ return request .keepAlive ().getMillis ();
840
815
} else {
841
- return defaultKeepAlive ;
816
+ return request .readerId () == null ? defaultKeepAlive : -1 ;
817
+ }
818
+ }
819
+
820
+ private long getScrollKeepAlive (Scroll scroll ) {
821
+ if (scroll != null && scroll .keepAlive () != null ) {
822
+ return scroll .keepAlive ().getMillis ();
842
823
}
824
+ return defaultKeepAlive ;
843
825
}
844
826
845
827
private void checkKeepAliveLimit (long keepAlive ) {
@@ -1150,29 +1132,39 @@ public AliasFilter buildAliasFilter(ClusterState state, String index, Set<String
1150
1132
return indicesService .buildAliasFilter (state , index , resolvedExpressions );
1151
1133
}
1152
1134
1135
+ public void canMatch (ShardSearchRequest request , ActionListener <CanMatchResponse > listener ) {
1136
+ try {
1137
+ listener .onResponse (canMatch (request ));
1138
+ } catch (IOException e ) {
1139
+ listener .onFailure (e );
1140
+ }
1141
+ }
1142
+
1153
1143
/**
1154
1144
* This method uses a lightweight searcher without wrapping (i.e., not open a full reader on frozen indices) to rewrite the query
1155
1145
* to check if the query can match any documents. This method can have false positives while if it returns {@code false} the query
1156
1146
* won't match any documents on the current shard.
1157
1147
*/
1158
1148
public CanMatchResponse canMatch (ShardSearchRequest request ) throws IOException {
1149
+ return canMatch (request , true );
1150
+ }
1151
+
1152
+ private CanMatchResponse canMatch (ShardSearchRequest request , boolean checkRefreshPending ) throws IOException {
1159
1153
assert request .searchType () == SearchType .QUERY_THEN_FETCH : "unexpected search type: " + request .searchType ();
1160
- final ReaderContext readerContext = request .readerId () != null ? findReaderContext (request .readerId (), request ) : null ;
1161
- final Releasable markAsUsed = readerContext != null ? readerContext . markAsUsed ( ) : null ;
1154
+ final ReaderContext readerContext = request .readerId () != null ? findReaderContext (request .readerId (), request ) : null ;
1155
+ final Releasable markAsUsed = readerContext != null ? updateKeepAliveAndMarkAsUsed ( readerContext , getKeepAlive ( request ) ) : null ;
1162
1156
try (markAsUsed ) {
1163
1157
final IndexService indexService ;
1164
1158
final Engine .Searcher canMatchSearcher ;
1165
1159
final boolean hasRefreshPending ;
1166
1160
if (readerContext != null ) {
1167
- checkKeepAliveLimit (request .keepAlive ().millis ());
1168
- readerContext .keepAlive (request .keepAlive ().millis ());
1169
1161
indexService = readerContext .indexService ();
1170
1162
canMatchSearcher = readerContext .acquireSearcher (Engine .CAN_MATCH_SEARCH_SOURCE );
1171
1163
hasRefreshPending = false ;
1172
1164
} else {
1173
1165
indexService = indicesService .indexServiceSafe (request .shardId ().getIndex ());
1174
1166
IndexShard indexShard = indexService .getShard (request .shardId ().getId ());
1175
- hasRefreshPending = indexShard .hasRefreshPending ();
1167
+ hasRefreshPending = indexShard .hasRefreshPending () && checkRefreshPending ;
1176
1168
canMatchSearcher = indexShard .acquireSearcher (Engine .CAN_MATCH_SEARCH_SOURCE );
1177
1169
}
1178
1170
@@ -1197,14 +1189,6 @@ public CanMatchResponse canMatch(ShardSearchRequest request) throws IOException
1197
1189
}
1198
1190
}
1199
1191
1200
- public void canMatch (ShardSearchRequest request , ActionListener <CanMatchResponse > listener ) {
1201
- try {
1202
- listener .onResponse (canMatch (request ));
1203
- } catch (IOException e ) {
1204
- listener .onFailure (e );
1205
- }
1206
- }
1207
-
1208
1192
/**
1209
1193
* Returns true iff the given search source builder can be early terminated by rewriting to a match none query. Or in other words
1210
1194
* if the execution of the search request can be early terminated without executing it. This is for instance not possible if
0 commit comments