public BlurResultIterable query(final String table, final BlurQuery blurQuery, AtomicLongArray facetedCounts)
throws Exception {
boolean runSlow = DEBUG_RUN_SLOW.get();
final AtomicBoolean running = new AtomicBoolean(true);
User user = UserContext.getUser();
final QueryStatus status = _statusManager.newQueryStatus(table, blurQuery, _threadCount, running,
UserConverter.toThriftUser(user));
_queriesExternalMeter.mark();
try {
Map<String, BlurIndex> blurIndexes;
try {
blurIndexes = _indexServer.getIndexes(table);
} catch (IOException e) {
LOG.error("Unknown error while trying to fetch index readers.", e);
throw new BException(e.getMessage(), e);
}
String rowId = blurQuery.getRowId();
if (rowId != null) {
// reduce the index selection down to the only one that would contain
// the row.
Map<String, BlurIndex> map = new HashMap<String, BlurIndex>();
String shard = MutationHelper.getShardName(table, rowId, getNumberOfShards(table), _blurPartitioner);
BlurIndex index = getBlurIndex(table, shard);
map.put(shard, index);
blurIndexes = map;
}
Tracer trace = Trace.trace("query setup", Trace.param("table", table));
ShardServerContext shardServerContext = ShardServerContext.getShardServerContext();
ParallelCall<Entry<String, BlurIndex>, BlurResultIterable> call;
TableContext context = getTableContext(table);
FieldManager fieldManager = context.getFieldManager();
org.apache.blur.thrift.generated.Query simpleQuery = blurQuery.query;
ReadInterceptor interceptor = context.getReadInterceptor();
Filter readFilter = interceptor.getFilter();
if (rowId != null) {
if (simpleQuery.recordFilter == null) {
simpleQuery.recordFilter = "+" + BlurConstants.ROW_ID + ":" + rowId;
} else {
simpleQuery.recordFilter = "+" + BlurConstants.ROW_ID + ":" + rowId + " +(" + simpleQuery.recordFilter + ")";
}
}
Filter recordFilterForSearch = QueryParserUtil.parseFilter(table, simpleQuery.recordFilter, false, fieldManager,
_filterCache, context);
Filter rowFilterForSearch = QueryParserUtil.parseFilter(table, simpleQuery.rowFilter, true, fieldManager,
_filterCache, context);
Filter docFilter;
if (recordFilterForSearch == null && readFilter != null) {
docFilter = readFilter;
} else if (recordFilterForSearch != null && readFilter == null) {
docFilter = recordFilterForSearch;
} else if (recordFilterForSearch != null && readFilter != null) {
// @TODO dangerous call because of the bitsets that booleanfilter
// creates.
BooleanFilter booleanFilter = new BooleanFilter();
booleanFilter.add(recordFilterForSearch, Occur.MUST);
booleanFilter.add(readFilter, Occur.MUST);
docFilter = booleanFilter;
} else {
docFilter = null;
}
Query userQuery = QueryParserUtil.parseQuery(simpleQuery.query, simpleQuery.rowQuery, fieldManager,
rowFilterForSearch, docFilter, getScoreType(simpleQuery.scoreType), context);
Query facetedQuery;
FacetExecutor executor = null;
if (blurQuery.facets != null) {
long[] facetMinimums = getFacetMinimums(blurQuery.facets);
executor = new FacetExecutor(blurQuery.facets.size(), facetMinimums, facetedCounts, running);
facetedQuery = new FacetQuery(userQuery, getFacetQueries(blurQuery, fieldManager, context, rowFilterForSearch,
recordFilterForSearch), executor);
} else {
facetedQuery = userQuery;
}
Sort sort = getSort(blurQuery, fieldManager);
call = new SimpleQueryParallelCall(running, table, status, facetedQuery, blurQuery.selector,
_queriesInternalMeter, shardServerContext, runSlow, _fetchCount, _maxHeapPerRowFetch,
context.getSimilarity(), context, sort, _deepPagingCache);
trace.done();
MergerBlurResultIterable merger = new MergerBlurResultIterable(blurQuery);
BlurResultIterable merge = ForkJoin.execute(_executor, blurIndexes.entrySet(), call, new Cancel() {
@Override
public void cancel() {
running.set(false);
}
}).merge(merger);
if (executor != null) {
executor.processFacets(_facetExecutor);
}
return fetchDataIfNeeded(merge, table, blurQuery.getSelector());
} catch (StopExecutionCollectorException e) {
BlurQueryStatus queryStatus = status.getQueryStatus();
QueryState state = queryStatus.getState();
if (state == QueryState.BACK_PRESSURE_INTERRUPTED) {
throw new BlurException("Cannot execute query right now.", null, ErrorType.BACK_PRESSURE);
} else if (state == QueryState.INTERRUPTED) {
throw new BlurException("Cannot execute query right now.", null, ErrorType.QUERY_CANCEL);
}
throw e;
} catch (ExitingReaderException e) {
BlurQueryStatus queryStatus = status.getQueryStatus();
QueryState state = queryStatus.getState();
if (state == QueryState.BACK_PRESSURE_INTERRUPTED) {
throw new BlurException("Cannot execute query right now.", null, ErrorType.BACK_PRESSURE);
} else if (state == QueryState.INTERRUPTED) {
throw new BlurException("Cannot execute query right now.", null, ErrorType.QUERY_CANCEL);