mirror of https://github.com/apache/lucene.git
SOLR-5986: Fix tests and start returning partial results in case of ExitingReaderException
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1630583 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
2da8697230
commit
3f603bdd87
|
@ -54,6 +54,8 @@ import org.apache.solr.search.SolrReturnFields;
|
|||
import org.apache.solr.search.SortSpec;
|
||||
import org.apache.solr.search.SyntaxError;
|
||||
import org.apache.solr.util.SolrPluginUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
|
@ -78,6 +80,8 @@ public class MoreLikeThisHandler extends RequestHandlerBase
|
|||
// Pattern is thread safe -- TODO? share this with general 'fl' param
|
||||
private static final Pattern splitList = Pattern.compile(",| ");
|
||||
|
||||
protected static Logger log = LoggerFactory.getLogger(MoreLikeThisHandler.class);
|
||||
|
||||
@Override
|
||||
public void init(NamedList args) {
|
||||
super.init(args);
|
||||
|
@ -267,8 +271,7 @@ public class MoreLikeThisHandler extends RequestHandlerBase
|
|||
}
|
||||
}
|
||||
} catch (ExitableDirectoryReader.ExitingReaderException ex) {
|
||||
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
|
||||
"MLTHandler Request took too long during query expansion. Terminating request.");
|
||||
log.warn( "Query: " + req.getParamString() + "; " + ex.getMessage());
|
||||
} finally {
|
||||
SolrQueryTimeoutImpl.reset();
|
||||
}
|
||||
|
|
|
@ -244,8 +244,6 @@ public class SearchHandler extends RequestHandlerBase implements SolrCoreAware ,
|
|||
}
|
||||
} catch (ExitableDirectoryReader.ExitingReaderException ex) {
|
||||
log.warn( "Query: " + req.getParamString() + "; " + ex.getMessage());
|
||||
throw new SolrException(ErrorCode.BAD_REQUEST,
|
||||
"Request took too long during query expansion. Terminating request.");
|
||||
} finally {
|
||||
SolrQueryTimeoutImpl.reset();
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.apache.lucene.index.ExitableDirectoryReader;
|
||||
import org.apache.lucene.index.StorableField;
|
||||
import org.apache.lucene.queries.function.FunctionQuery;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
|
@ -452,6 +453,9 @@ public class Grouping {
|
|||
} catch (TimeLimitingCollector.TimeExceededException x) {
|
||||
logger.warn( "Query: " + query + "; " + x.getMessage() );
|
||||
qr.setPartialResults(true);
|
||||
} catch (ExitableDirectoryReader.ExitingReaderException e) {
|
||||
logger.warn( "Query: " + query + "; " + e.getMessage() );
|
||||
qr.setPartialResults(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -232,6 +232,9 @@ public class SolrIndexSearcher extends IndexSearcher implements Closeable,SolrIn
|
|||
catch( TimeLimitingCollector.TimeExceededException x ) {
|
||||
log.warn( "Query: " + query + "; " + x.getMessage() );
|
||||
qr.setPartialResults(true);
|
||||
} catch ( ExitableDirectoryReader.ExitingReaderException e) {
|
||||
log.warn("Query: " + query + "; " + e.getMessage());
|
||||
qr.setPartialResults(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1217,11 +1220,15 @@ public class SolrIndexSearcher extends IndexSearcher implements Closeable,SolrIn
|
|||
protected DocSet getDocSetNC(Query query, DocSet filter) throws IOException {
|
||||
DocSetCollector collector = new DocSetCollector(maxDoc()>>6, maxDoc());
|
||||
|
||||
if (filter==null) {
|
||||
super.search(query,null,collector);
|
||||
} else {
|
||||
Filter luceneFilter = filter.getTopFilter();
|
||||
super.search(query, luceneFilter, collector);
|
||||
try {
|
||||
if (filter == null) {
|
||||
super.search(query, null, collector);
|
||||
} else {
|
||||
Filter luceneFilter = filter.getTopFilter();
|
||||
super.search(query, luceneFilter, collector);
|
||||
}
|
||||
} catch ( ExitableDirectoryReader.ExitingReaderException e) {
|
||||
log.warn("Query: " + query + "; " + e.getMessage());
|
||||
}
|
||||
return collector.getDocSet();
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.util.ArrayList;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.lucene.index.ExitableDirectoryReader;
|
||||
import org.apache.lucene.queries.function.ValueSource;
|
||||
import org.apache.lucene.search.Collector;
|
||||
import org.apache.lucene.search.Filter;
|
||||
|
@ -230,6 +231,9 @@ public class CommandHandler {
|
|||
} catch (TimeLimitingCollector.TimeExceededException x) {
|
||||
partialResults = true;
|
||||
logger.warn( "Query: " + query + "; " + x.getMessage() );
|
||||
} catch (ExitableDirectoryReader.ExitingReaderException e) {
|
||||
partialResults = true;
|
||||
logger.warn( "Query: " + query + "; " + e.getMessage() );
|
||||
}
|
||||
|
||||
if (includeHitCount) {
|
||||
|
|
|
@ -503,24 +503,17 @@ public class TestDistributedSearch extends BaseDistributedSearchTestCase {
|
|||
ShardParams.SHARDS_TOLERANT, "true");
|
||||
|
||||
// test group query
|
||||
// TODO: Remove this? This doesn't make any real sense now that timeAllowed might trigger early
|
||||
// termination of the request during Terms enumeration/Query expansion.
|
||||
// During such an exit, partial results isn't supported as it wouldn't make any sense.
|
||||
// Increasing the timeAllowed from 1 to 100 for now.
|
||||
//
|
||||
// TODO: still failing in jenkins - see SOLR-5986
|
||||
//
|
||||
// queryPartialResults(upShards, upClients,
|
||||
// "q", "*:*",
|
||||
// "rows", 100,
|
||||
// "fl", "id," + i1,
|
||||
// "group", "true",
|
||||
// "group.query", t1 + ":kings OR " + t1 + ":eggs",
|
||||
// "group.limit", 10,
|
||||
// "sort", i1 + " asc, id asc",
|
||||
// CommonParams.TIME_ALLOWED, 100,
|
||||
// ShardParams.SHARDS_INFO, "true",
|
||||
// ShardParams.SHARDS_TOLERANT, "true");
|
||||
queryPartialResults(upShards, upClients,
|
||||
"q", "*:*",
|
||||
"rows", 100,
|
||||
"fl", "id," + i1,
|
||||
"group", "true",
|
||||
"group.query", t1 + ":kings OR " + t1 + ":eggs",
|
||||
"group.limit", 10,
|
||||
"sort", i1 + " asc, id asc",
|
||||
CommonParams.TIME_ALLOWED, 1,
|
||||
ShardParams.SHARDS_INFO, "true",
|
||||
ShardParams.SHARDS_TOLERANT, "true");
|
||||
|
||||
queryPartialResults(upShards, upClients,
|
||||
"q", "*:*",
|
||||
|
|
|
@ -20,15 +20,11 @@ package org.apache.solr.cloud;
|
|||
|
||||
import org.apache.lucene.util.LuceneTestCase.Slow;
|
||||
import org.apache.lucene.util.TestUtil;
|
||||
import org.apache.solr.client.solrj.SolrServerException;
|
||||
import org.apache.solr.client.solrj.response.QueryResponse;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.common.params.ModifiableSolrParams;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import static org.apache.solr.common.SolrException.ErrorCode;
|
||||
|
||||
/**
|
||||
* Distributed test for {@link org.apache.lucene.index.ExitableDirectoryReader}
|
||||
*/
|
||||
|
@ -74,7 +70,7 @@ public class CloudExitableDirectoryReaderTest extends AbstractFullDistribZkTestB
|
|||
}
|
||||
|
||||
public void doTimeoutTests() throws Exception {
|
||||
assertFail(params("q", "name:a*", "timeAllowed", "1"));
|
||||
assertPartialResults(params("q", "name:a*", "timeAllowed", "1"));
|
||||
|
||||
/*
|
||||
query rewriting for NUM_DOCS_PER_TYPE terms should take less
|
||||
|
@ -86,7 +82,7 @@ public class CloudExitableDirectoryReaderTest extends AbstractFullDistribZkTestB
|
|||
Long timeAllowed = TestUtil.nextLong(random(), fiveSeconds, Long.MAX_VALUE);
|
||||
assertSuccess(params("q", "name:a*", "timeAllowed",timeAllowed.toString()));
|
||||
|
||||
assertFail(params("q", "name:a*", "timeAllowed", "1"));
|
||||
assertPartialResults(params("q", "name:a*", "timeAllowed", "1"));
|
||||
|
||||
timeAllowed = TestUtil.nextLong(random(), fiveSeconds, Long.MAX_VALUE);
|
||||
assertSuccess(params("q", "name:b*", "timeAllowed",timeAllowed.toString()));
|
||||
|
@ -100,37 +96,14 @@ public class CloudExitableDirectoryReaderTest extends AbstractFullDistribZkTestB
|
|||
/**
|
||||
* execute a request, verify that we get an expected error
|
||||
*/
|
||||
public void assertFail(ModifiableSolrParams p) throws Exception {
|
||||
String timeoutMessage = "Request took too long during query expansion. Terminating request.";
|
||||
|
||||
try {
|
||||
ignoreException(timeoutMessage);
|
||||
queryServer(p);
|
||||
fail("no exception matching expected: " + ErrorCode.BAD_REQUEST.code + ": " + timeoutMessage);
|
||||
} catch (SolrServerException e) {
|
||||
assertTrue("Exception " + e.getCause() + " is not a SolrException:\n" + prettyStackTrace(e.getCause()),
|
||||
e.getCause() instanceof SolrException);
|
||||
assertEquals(ErrorCode.BAD_REQUEST.code, ((SolrException)e.getCause()).code());
|
||||
assertTrue("Expected error message substr not found: " + timeoutMessage + " <!< " + e.getMessage(),
|
||||
e.getMessage().contains(timeoutMessage));
|
||||
} finally {
|
||||
unIgnoreException(timeoutMessage);
|
||||
}
|
||||
public void assertPartialResults(ModifiableSolrParams p) throws Exception {
|
||||
QueryResponse rsp = queryServer(p);
|
||||
assertEquals("partialResults were expected", true, rsp.getHeader().get("partialResults"));
|
||||
}
|
||||
|
||||
public void assertSuccess(ModifiableSolrParams p) throws Exception {
|
||||
QueryResponse response = queryServer(p);
|
||||
assertEquals("Wrong #docs in response", NUM_DOCS_PER_TYPE - 1, response.getResults().getNumFound());
|
||||
}
|
||||
|
||||
public String prettyStackTrace(Throwable t) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (StackTraceElement elem : t.getStackTrace()) {
|
||||
builder.append(" at ");
|
||||
builder.append(elem.toString());
|
||||
builder.append('\n');
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@ package org.apache.solr.core;
|
|||
|
||||
import org.apache.solr.SolrTestCaseJ4;
|
||||
import org.apache.solr.common.SolrException;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.response.SolrQueryResponse;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -31,6 +33,7 @@ public class ExitableDirectoryReaderTest extends SolrTestCaseJ4 {
|
|||
|
||||
static int NUM_DOCS_PER_TYPE = 100;
|
||||
static final String assertionString = "//result[@numFound='"+ (NUM_DOCS_PER_TYPE - 1) + "']";
|
||||
static final String failureAssertionString = "/responseHeader/partialResults==true]";
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws Exception {
|
||||
|
@ -57,16 +60,12 @@ public class ExitableDirectoryReaderTest extends SolrTestCaseJ4 {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testPrefixQuery() {
|
||||
assertQEx("", req("q","name:a*", "indent","true","timeAllowed","1")
|
||||
, SolrException.ErrorCode.BAD_REQUEST
|
||||
);
|
||||
public void testPrefixQuery() throws Exception {
|
||||
assertJQ(req("q", "name:a*", "indent", "true", "timeAllowed", "1"), failureAssertionString);
|
||||
|
||||
assertQ(req("q","name:a*", "indent","true", "timeAllowed","10000"), assertionString);
|
||||
|
||||
assertQEx("", req("q","name:a*", "indent","true", "timeAllowed","1")
|
||||
, SolrException.ErrorCode.BAD_REQUEST
|
||||
);
|
||||
assertJQ(req("q","name:a*", "indent","true", "timeAllowed","1"), failureAssertionString);
|
||||
|
||||
assertQ(req("q","name:b*", "indent","true", "timeAllowed","10000"), assertionString);
|
||||
|
||||
|
@ -78,18 +77,16 @@ public class ExitableDirectoryReaderTest extends SolrTestCaseJ4 {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testQueriesOnDocsWithMultipleTerms() {
|
||||
public void testQueriesOnDocsWithMultipleTerms() throws Exception {
|
||||
assertQ(req("q","name:dummy", "indent","true", "timeAllowed","10000"), assertionString);
|
||||
|
||||
// This should pass even though this may take more than the 'timeAllowed' time, it doesn't take long
|
||||
// to iterate over 1 term (dummy).
|
||||
assertQ(req("q","name:dummy", "indent","true", "timeAllowed","10000"), assertionString);
|
||||
|
||||
assertQEx("", req("q","name:doc*", "indent","true", "timeAllowed","1")
|
||||
, SolrException.ErrorCode.BAD_REQUEST
|
||||
);
|
||||
assertQ(req("q", "name:dummy", "indent", "true", "timeAllowed", "10000"), assertionString);
|
||||
|
||||
assertJQ(req("q", "name:doc*", "indent", "true", "timeAllowed", "1"), failureAssertionString);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue